• 为什么要实现继承? 个人认为,复用场景是非常常见的,故继承能够实现的复用也尤为的频繁,具体场景可能需要具体实践。

以下是五种实现继承的方式。

提前说明: 有类的概念的人,应该清楚,一个实例首先他有自身的属性(创建自构造函数),那么在继承的时候,父类的构造函数的属性就可能与其想重叠等,一般来说,名字相同则覆盖,不同则均存在呀。(到这里构造函数的继承关系差不多就说完了)。

然后就是原型链上的继承,也就是父类的这个构造函数的原型(prototype),会继承该原型上的属性(注意,这里明显原型继承和构造函数继承不是一个东西哦)。

(代码全部都是简写哦)

1、原型链继承

只需要在子类的构造函数的原型赋值为要继承的父类的实例即可。

Man.prototype = new Person('pursue');//man是子类,person是父类

2、构造函数继承

在子类的构造函数中,使用父类构造函数但是绑定当前this对象,并将子类构造函数接收到的参数(arguments)传给父类构造函数。

function Man(name, age, othernames) {

  Person.apply(this, arguments);//没有参数时,也可以使用call(this);
  this.othernames = othernames;//由于给父类传参按顺序赋值,故可以将本子类参数放在后面的位置,绑定this构造完父类之后再进行子类属性的赋值。

}

3、组合继承

就是原型链和构造函数的组合。

4、原型式继承

let fu = {
	name:'kong',
    age:0
};
function yuanXingShi(fu){
	function Zi(){};
    Zi.prototype = fu;
    let zi = new Zi();
    reuturn zi;
};
let use = yuanXingShi(fu)
//es5 可以直接使用   let use = Object.create(fu);

和原型链的区别是,使用了函数封装,可以将想要继承的父类实例传入,然后返回子类实例。如上代码可以明显看出实际是在增加属性。但其实由于是原型继承,故如果该实例的原型上存在其他属性等,仍然是可以使用的。

5、寄生式继承

其他实践出来的知识

如果实例和其实例原型上存在相同属性,是优先使用自己原型上的属性的。 alt

你不知道的js:“如果属性名 foo 同时存在于 myObject 本身和从 myObject 开始的 [[Prototype]] 链的更高层,这样的情况称为 遮蔽。直接存在于 myObject 上的 foo 属性会 遮蔽 任何出现在链条高层的 foo 属性,因为 myObject.foo 查询总是在寻找链条最底层的 foo 属性。”

遮蔽:

当 foo 不直接存在 于 myObject,但 存在 于 myObject 的 [[Prototype]] 链的更高层时,有三种情况,具体深入较为复杂,暂时省略。

如下是隐式遮蔽:

var anotherObject = {
	a: 2
};

var myObject = Object.create( anotherObject );

anotherObject.a; // 2
myObject.a; // 2

anotherObject.hasOwnProperty( "a" ); // true
myObject.hasOwnProperty( "a" ); // false

myObject.a++; // 噢,隐式遮蔽!

anotherObject.a; // 2
myObject.a; // 3

另外的例子:

alt

简单说就是:如果你对继承的属性进行修改,他会自动新增属性到自身实例上。

书中说:"虽然看起来 myObject.a++ 应当(通过委托)查询并 原地 递增 anotherObject.a 属性,但是 ++ 操作符相当于 myObject.a = myObject.a + 1。结果就是在 [[Prototype]] 上进行 a 的 [[Get]] 查询,从 anotherObject.a 得到当前的值 2,将这个值递增1,然后将值 3 用 [[Put]] 赋值到 myObject 上的新遮蔽属性 a 上。"

浅拷贝:

var myObject = Object.create( anotherObject );//这个是原型式继承!

对于js来说,委托一词要更合适于继承来描述


instanceof 和isPrototypeOf 和 Object.create

Object.create的返回值是一个实例(同原型式继承)

a instanceof b:a是一个实例,而b是指一个构造函数,由于Object.create的返回值是一个实例,故是在要比较就要用".constructor"

var a = {};
var b = Object.create( a );
b instanceof a.constructor;//true

a.isPrototypeOf(b) : bc[[Prototype]] 链中出现过吗?

var a = {};
var b = Object.create( a );
a.isPrototypeOf(b) ;//true

js实现继承的方法中为何总是要修正constructor方法的指向呢?

var cat2 = new cat.__proto__.constructor(); // Animal called 

就是为了避免这样的错误发生,规避错误。