1 构造函数
1.1 什么是构造函数
构造函数相当于其他编程语言里的类(ES6 中引入了类的概念),每个对象都有与之对应的构造函数,构造函数描述对象的特性(属性和方法)。对象是构造函数的实例,构造函数是对象的抽象。一个构造函数可以对应多个对象,一个对象只对应一个构造函数。
1.2 判断对象的构造函数
① 运算符 instanceof
二元运算符,返回布尔值。
对象 instanceof 构造函数;
注:
对象与自己的构造函数,成立
对象与它的原型链上的对象的构造函数,成立
JS中所有的对象(除了修改过原型链)与 Object 都成立
② constructor 属性
任何一个对象都有该属性,值为该对象的构造函数。
对象.constructor
注:
- 每个对象都有
constructor
属性,但不一定在自己身上(可用hasOwnProperty
判断)。对象通过constructor
属性,能够获取对象的构造函数,但是不是所有的对象都是准确的,如果一个对象上有constructor
属性,其值是指向以该对象为原型的对象的构造函数。- 对象a 的 原型是对象 b:
- 对象a本身上没有
constructor
属性,使用的是原型上的属性,结果得到就是 a 的构造函数。- 对象a本身上有
constructor
,值指向以自己为原型的对象(a)的构造函数。
1.3 自定义构造函数
// 定义构造函数 描述用户信息
function User(username, pwd, address) {
// 定义实例的属性
this.username = username;
this.pwd = pwd;
this.address = address;
// 定义实例的方法
this.addShopcart = function() {
console.log(this.username + ' 把一件商品加入了购物车!');
}
this.addOrder = function() {
console.log(this.username + ' 下单了, 请送到' + this.address);
}
}
1.4 实例化
new User();
new User('曹操', '123456', '安徽亳州');
注:
实例化构造函数时,构造函数体中的语句会执行。
构造函数的返回值问题:
① 如果构造函数中没有 return 或者 return 的是原始类型的数据(number、string、boolean),实例化得到新的对象,与返回值无关;
② 如果构造函数中 return 的是对象类型的数据(如:Array、Function),实例化得到的是返回值。
构造函数本质上仍是函数,即可调用也可实例化。为了区分,一般构造函数的首字母大写。是函数还是构造函数取决于如何使用:如果调用,就是函数;如果实例化,就是构造函数。
2 this
2.1 this的含义
this 是 JS 中内置的一个变量,值由系统给出,通常在函数中使用。
2.2 this的指向(this 的值)
在构造函数中使用this: this 的值是构造函数将来实例化出来的对象。
在函数(方法)中使用this: this的值是调用该函数(方法)的对象。
2.3 window
- JS中有一个全局对象,所有全局变量都是全局对象的属性,所有全局函数都是全局对象的方法。运行在浏览器上的JS,全局对象是
window
。 - 一打开页面,
window
对象可以自动创建。 - 使用全局对象的属性和方法,可以把前面的window. 省略。
3 原型
3.1 原型的概念
原型是个对象,每个对象都有原型,对象可以继承原型上的属性和方法。
3.2 如何获取对象的原型
① 隐式获取
对象.__proto__
② 显示获取
对象的构造函数.prototype
注:对象的构造函数.prototype获取的是该构造函数的实例(对象)的原型,不是构造函数自身的原型!
3.3 对象、构造函数、原型之间的关系
① 对象和构造函数
- 对象是构造函数的实例,构造函数是对象的抽象(描述)。
- 一个构造函数对应多个对象,一个对象只对应一个构造函数。
② 对象和原型
- 每个对象都有原型
- 对象可以继承原型上的属性和方法
③ 构造函数和原型
- 通过构造函数的 prototype 可以获取其实例(对象)的原型。
- 默认情况下,构造函数相同的对象,其原型也相同。
3.4 自定义构造函数时原型的应用
自定义构造函数时将方法添加到实例的原型上,这样不必为每一个实例都开辟一块内存空间存放其方法,节省了内存空间。
// 定义用户 构造函数
function User(username, pwd, address) {
// 设置实例的属性
this.username = username;
this.pwd = pwd;
this.address = address;
}
// 把方法添加到实例的原型上
User.prototype.addShopcart = function() {
console.log(this.username + ' 添加商品到购物车!');
};
User.prototype.addOrder = function() {
console.log(this.username + ' 下单了,请邮寄到 ' + this.address);
};
3.5 判断属性是否属于对象本身
判断属性是否是对象本身上的属性,返回布尔值。如果属性在对象本身上,返回 true; 如果属性在对象的原型上或者没有这个属性,返回 false。
对象.hasOwnProperty('属性名');
注:
与 in 运算符的区别:对象本身的属性和原型上的属性,in 运算符都得到 true
3.6 创建对象的同时指定原型
Object.create(原型)
// 创建一个没有原型的对象
Object.create(null);
// 创建一个新对象,指定[100,200,300]为原型
Object.create([100,200,300]);
4 原型链
4.1 原型链的概念
对象的原型仍然是个对象类型的数据,所以原型也具有原型,直到一个顶层原型对象, 形成了原型链。
4.2 属性查找过程
原型链描述对象中属性的查找过程:
当使用对象中某个属性的时候,先从对象本身查找,如果没有再去原型上查找,还没有继续上层原型查找,直到顶层原型,哪里找到哪里停止查找,如果一直到顶层原型仍然找不到,自动得到 undefined
。