[!NOTE]

能熟练掌握每种继承方式的手写实现,并知道该继承实现方式的优缺点。

原型链继承原型

原型链#

任何一个实例对象通过原型链可以找到它对应的原型对象,原型对象上面!

的实例和方法都是实例所共享的。

一个对象在查找以一个方法或属性时,他会先在自己的对象上去找,找不到时,他会沿着原型链依次向上查找。

注意: 函数才有prototype,实例对象只有有__proto__, 而函数有的__proto__是因为函数是Function的实例对象

instanceof原理#

判断实例对象的__proto__属性与构造函数的prototype是不是用一个引用。如果不是,他会沿着对象的__proto__向上查找的,直到顶端Object。

判断对象是哪个类的直接实例#

使用对象.construcor直接可判断

构造函数,new时发生了什么?#

Copy
var obj = {}; obj.__proto__ = Base.prototype; Base.call(obj);
  1. 创建一个新的对象 obj;
  2. 将这个空对象的__proto__成员指向了Base函数对象prototype成员对象
  3. Base函数对象的this指针替换成obj, 相当于执行了Base.call(obj);
  4. 如果构造函数显示的返回一个对象,那么则这个实例为这个返回的对象。 否则返回这个新创建的对象

#

类的声明

Copy
// 普通写法 function Animal() { this.name = 'name' } // ES6 class Animal2 { constructor () { this.name = 'name'; } }

继承#

借用构造函数法#

在构造函数中 使用Parent.call(this)的方法继承父类属性。

原理: 将子类的this使用父类的构造函数跑一遍

缺点: Parent原型链上的属性和方法并不会被子类继承

Copy
function Parent() { this.name = 'parent' } function Child() { Parent.call(this); this.type = 'child' }

原型链实现继承#

原理:把子类的prototype(原型对象)直接设置为父类的实例

缺点:因为子类只进行一次原型更改,所以子类的所有实例保存的是同一个父类的值。
当子类对象上进行值修改时,如果是修改的原始类型的值,那么会在实例上新建这样一个值;
但如果是引用类型的话,他就会去修改子类上唯一一个父类实例里面的这个引用类型,这会影响所有子类实例

Copy
function Parent() { this.name = 'parent' this.arr = [1,2,3] } function Child() {