总结
- 构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型有一个属性(constructor)指回构造函数,而实例有一个内部指针(proto)指向原型(prototype);
- 原型链:每个实例对象(object)都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(proto),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
- 原型与实例的关系可以通过两种方式来确定:第一种方式是使用 instanceof 操作符,如果一个实例的原型链中出现过相应的构造函数,则 instanceof 返回 true;第二种方式是使用 isPrototypeOf()方法,原型链中的每个原型都可以调用这个方法,如下例所示,只要原型链中包含这个原型,这个方法就返回 true:
- 原型链的问题:1.给原型加引用属性时,引用属性的改变,会影响其它使用这个原型的实例对象,instance1.colors.push(“black”),影响了instance2;2.子类型在实例化时不能给父类型的构造函数传参(原型链基本不会被单独使用)
- 盗用构造函数:在子类 构造函数中调用父类构造函数,用于解决原型包含引用值导致的继承问题相比于使用原型链,盗用构造函数的一个优点就是可以在子类构造函数中向父类构造函数传参
- 盗用构造函数的不足:必须在构造函数中定义方法,因此函数不能重用;子类也不能访问父类原型上定义的方法,因此所有类型只能使用构造函数模 式。由于存在这些问题,盗用构造函数基本上也不能单独使用。
- 组合继承:(有时候也叫伪经典继承)综合了原型链和盗用构造函数,将两者的优点集中了起来;基本的思路是使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。
- 组合继承的优点:1.可以给构造函数传参;2.通过盗用构造函数继承实例属性;3.把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。不足:存在效率的问题,父类构造函数始终会被调用两次:一次在是 创建子类原型时调用,另一次是在子类构造函数中调用
- 原型式继承非常适合不需要单独创建构造函数,但仍然需要在对象间共享信息的场合,Object.create()就是原型式继承;不足:属性中包含的引用值始终会在相关对象间共享,跟使用原型模式是一样的
- 寄生式组合继承可以算是引用类型继承的最佳模式,说到底就是使用寄生式继承来继承父类原型,然后将返回的新对象赋值给子类原型。通过原型式继承,把父类的原型赋值给子类的原型;
问题
原型链,盗用构造函数,组合继承,原型式继承,寄生组合式继承的特点?
原型链
特点:将共用的属性方法统一放到原型对象
不足:1.给原型加引用属性时,引用属性的改变,会影响其它使用这个原型的实例对象;2.子类型在实例化时不 能给父类型的构造函数传参(原型链基本不会被单独使用)
盗用构造函数
特点:在子类构造函数中调用父类构造函数,用于解决原型包含引用值导致的继承问题,在子类构造函数中向父类构造函数传参(解决原型链不能传参的问题)
不足:必须在构造函数中定义方法,因此函数不能重用;子类也不能访问父类原型上定义的方法,因此所有类型只能使用构造函数模式。由于存在这些问题,盗用构造函数基本上也不能单独使用。
组合继承
特点:使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。
不足:存在效率的问题,父类构造函数始终会被调用两次:一次在是 创建子类原型时调用,另一次是在子类构造函数中调用
原型式继承(Object.create就是原型式继承)
特点:适合不需要单独创建构造函数,但仍然需要在对象间共享信息的场合;
不足:属性中包含的引用值始终会在相关对象间共享,跟使用原型模式是一样的
寄生式组合继承
特点:算是引用类型继承的最佳模式,解决了组合继承父类构造函数调用两次的问题