1. 对象原型和原型对象
- 所有引用类型(数组,函数,对象)都会有一个 __proto__属性,这个属性指向一个对象,所以有称为对象原型(隐式原型);并且__proto__属性上的方法或属性实例对象可以直接使用
- js规定每个函数都一个prototype属性,指向一个对象,称为原型对象(显式原型)
- 实例对象的对象原型__proto__会指向创建这个实例对象的构造函数的原型对象prototype,所以实例对象可以直接使用构造函数原型对象prototype上面的属性和方法
2. 构造函数
- 将对象的公共属性和方法抽离出来封装到一个函数(首字母大写),这个函数就叫做构造函数,通常与new关键字一起使用创建对象;new 关键字执行的步骤:先创建一个空对象,让构造函数内部的this指向这个空对象,为这个空对象添加属性和方法,返回这个对象
- 构造函数存在的问题:使用构造函数创建对象就是给对象添加属性和方法,每创建一个对象就会开辟一块内存空间来存取这个对象,但是方法是复杂数据类型,从而又会开辟一个内存空间来存取这个方法,我们知道构造函数内部给对象添加的方法是公共的方法,如果我们创建了一百个实例对象那又会额外开辟一百个内存空间来存取这个方法,这样就造成了内存浪费的问题,所以我们通常将这些公共且不变的方法定义在构造函数的原型对象上,供实例对象使用
function Fruit(params) {
this.params = params
}
Fruit.prototype.sing=function () {console.log('i can sing')}
const apple = new Fruit('apple')
apple.sing() // i can sing
3. 原型链
话不多说直接放图
第一张
第二张
原型链是用来给对象查找属性或方法用的,查找原则
- 先查找对象本身是否含有此属性或方法,若没找到走2
- 查找构造函数的原型对象prototype是否有此属性或方法,若没找到走3,(如果使用对象字面量和Object创建的对象忽略此步骤,因为这个两个创建的对象的对象原型__proto__直接指向的是Object构造函数的原型对象prototype)
- 查找Object构造函数的原型对象prototype是否含有此属性或方法,若没找到,如果是属性返回undefined,如果是调用方法则报错