一、面对对象的概述
1、面向过程与面向对象
总结:
面向过程思想:我们扮演的是执行者,凡事都要靠自己完成。
面向对象思想:我们扮演的是指挥官,只要找到相应的对象,让它们帮我们做具体的事情即可。
2、面向对象的特征(封装性、继承性、多态性)
(1)封装性
封装:指的是隐藏内部的实现细节,只对外开放操作接口。
接口:就是对象的方法,无论对象的内部多么复杂,用户只需知道这些接口怎么使用即可。
优势:无论一个对象内部的代码经过了多少次修改,只要不改变接口,就不会影响到使用这个对象时编写的代码。
(2)继承性
继承:是指一个对象继承另一个对象的成员,从而在不改变另一个对象的前提下进行扩展。
优势:可在保持接口兼容的前提下对功能进行扩展。
增强了代码的复用性,为程序的修改和补充提供便利。
(3)多态性
多态:指的是同一个操作作用于不同的对象,会产生不同的执行结果。
举例:数字、数组、函数都具有toString()方法,当使用不同的对象调用该方法时,执行结果不同。
var obj = 123;
console.log(obj.toString()); // 输出结果:123
obj = [1, 2, 3];
console.log(obj.toString()); // 输出结果:1,2,3
obj = function () { };
console.log(obj.toString()); // 输出结果:function () {}
温馨提示:在面向对象中,多态性的实现往往离不开继承,这是因为当多个对象继承了同一个对象后,就获得了相同的方法,然后根据每个对象的不同来改变同名方法的执行结果。
二、自定义对象
1、对象的定义
语法:对象的定义是通过“{ }”语法实现的。
组成:对象以对象成员(属性和方法)构成,多个成员之间使用逗号分隔。
成员:对象的成员以键值对的形式存放在{}中。
var qwq1 = {};
var qwq2 = { name: 'Tom' };
var qwq3 = { name: 'Tom', age: 19, gender: '男' };
var qwq4 = {
name: 'Tom',
age: 19,
gender: '男',
sayHello: function () {
console.log('对象的定义');
}
};
注意:“{ }”语法又称为对象的字面量语法,所谓字面量是指在源代码中直接书写的一个表示数据和类型的量,如123(数值型)、'123'(字符型)、[123](数组)都是字面量。
2、JSON数据格式
JSON: JavaScript Object Notation,JavaScript对象符号。
用途:应用于数据存储和交互。
语法: JSON是一个字符串,使用双引号包裹对象的成员名和字符串型的值。
JSON与对象的区别:JSON是一个字符串。
JSON不仅可以用来保存对象,还可以保存数字、字符串、数组等其他类型的数据。
[{ "name": "Tom", "age": 24 }, { "name": "Jim", "age": 25 }]
3、访问对象成员
语法:对象.成员。
var qwq5 = {}; // 创建一个空对象
qwq5.name = 'Tom'; // 为对象增加属性
qwq5.introduce = function () { // 为对象增加方法
alert('My name is ' + this.name); // 在方法中使用this代表当前对象
};
alert(qwq5.name); // 访问name属性,输出结果:Tom
qwq5.introduce(); // 调用introduce()方法,输出结果:My name is Tom
可变成员名语法:对象[变量名] = 值。
var qwq6 = {}; // 创建一个空对象
var key = 'id'; // 通过变量保存要操作的属性名
qwq6[key] = 123; // 相当于“qwq6['id'] = 123”或“qwq6.id = 123”
4、对象成员遍历
语法:for…in。
var obj = { name: '卖火柴的小男孩', age: 18 };
for (var qwq in obj) {
console.log(qwq + '-' + obj[qwq]);
}
变量qwq保存了每个对象成员的名称。
obj[qwq]访问成员属性的值。
obj[qwq]()调用成员方法。
5、判断对象成员是否存在
使用in运算符可以判断一个对象中的某个成员是否存在。
当对象的成员存在时返回true,不存在时返回false。
var obj = { name: 'Tom', age: 16 };
console.log('name' in obj); // 输出结果:true
console.log('gender' in obj); // 输出结果:false
6、深拷贝与浅拷贝
(1)拷贝(copy):是指将一个目标数据复制一份,形成两个个体。
(2)深拷贝:参与拷贝的两个目标,改变其中一个目标的值,不会影响另一个目标的值。
基本类型(如数值、字符型):通过变量赋值即可实现。
引用类型(如数组、对象):复制对象里的成员到另一个对象。
(3)浅拷贝:参与拷贝的两个目标,一个目标的值改变,另一个目标的值也会随之改变。
引用类型(如数组、对象):通过变量赋值即可实现。
提示:浅拷贝是引用类型中才有的概念。
优势:浅拷贝可以节省内存开销。
三、构造函数
1、为什么使用构造函数
构造函数:是JavaScript创建对象的另外一种方式。
与字面量方式创建对象对比:构造函数可以创建出一些具有相同特征的对象。
举例:通过数码产品构造函数创建电脑、手机、照相机对象。其特点在于这些对象都基于同一个模板创建,同时每个对象又有自己的特征。
字面量的方式创建对象的特点
优势:简单灵活。
劣势:当需要创建一组具有相同特征的对象时,无法通过代码指定这些对象应该具有哪些相同的成员。
面向对象编程语言的实现模板的方式:利用类(class)创建模板,根据模板实现不同的对象(类的实例)。
JavaScript实现模板:
方式1:通过工厂函数,在其内部通过字面量“{ }”的方式创建对象来实现,缺点是无法区分对象的类型。
方式2:通过构造函数创建对象。
2、JavaScript内置的构造函数
常见的内置构造函数:Object、String、Number等构造函数。
构造函数创建对象的语法:new 构造函数名()。
实例化与实例:人们习惯将使用new关键字创建对象的过程称为实例化,实例化后得到的对象称为构造函数的实例。
// 通过构造函数创建对象
var obj = new Object(); // 创建Object对象
var str = new String('123'); // 创建String对象
// 查看对象是由哪个构造函数创建的
console.log(obj.constructor); // 输出结果:function Object() { [native code] }
console.log(str.constructor); // 输出结果:function String() { [native code] }
console.log({}.constructor); // 输出结果:function Object() { [native code] }
“对象.constructor”属性指向了该对象的构造函数。
通过console.log()输出时,[native code]表示该函数的代码是内置的。
3、自定义构造函数
构造函数的命名推荐采用帕斯卡命名规则,即所有的单词首字母大写。
在构造函数内部,使用this来表示刚刚创建的对象。
// 使用构造函数
var qwq1 = new Person('Tom', 18);
var qwq2 = new Person('Jerry', 19);
console.log(qwq1);
console.log(qwq2);
qwq1.sayHello();
console.log(qwq1.constructor);
// 自定义构造函数
function Person(name, age) {
this.name = name;
this.age = age;
this.sayHello = function () {
console.log('Hello, my name is ' + this.name);
};
}
4、私有成员
概念:在构造函数中,使用