ECMAScript 中描述了原型链的概念,并将原型链作为实现继承的主要方法。其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。简单回顾一下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么,假如我们让原型对象等于另一个类型的实例,结果会怎么样呢?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条。这就是所谓原型链的基本概念。
摘自《JavaScript高级程序设计》原型链继承解释
简单的来说 原型链就是一种关系
一种实例对象和原型对象之间的关系,关系是通过原型__proto__ 来联系的
// 实现原型链有一种基本模式,其代码大致如下。
// 第一个构造函数
function SuperType() {
this.theShy = 'niubi'; // shy爹牛逼
}
//第二个构造函数
function SubType() {
this.xiaohu = '2200'; // ps: 一虎之力 奥利给
}
SuperType.prototype.getAbility = function () {
return this.theShy
}
SubType.prototype.shuchu = function () {
return this.xiaohu
}
// SubType的原型继承了 SuperType
// 这样会重写SubType.prototype中constructor中的值 指向SuperType
SubType.prototype = new SuperType();
// 让构造器的指向更改回正确的指向
SubType.prototype.constructor = SubType;
var instance = new SubType();
console.log(instance); // 图1-1
instance.theShy = 'too niubi'
var instance2 = new SubType();
console.log(instance2.theShy) // 'too niubi'
// 通过原型链继承 所有实例公用一套变量 在一个实例中对变量进行了改变 ,则所有实例中的变量都被改变了
console.log(instance.getAbility()); // 'niubi'
原型链继承的优缺点
优点:能通过instanceOf和isPrototypeOf的检测
注意:给原型添加方法的语句一定要放在原型替换SubType.prototype = new SuperType();之后
缺点:(1)SuperType中的属性(不是方法)也变成了SubType的prototype中的公用属性,
如上面例子中的theshy属性,被instance修改后 instance2.theshy获得的是被修改后的变量
(2)创建子类型的时候,不能像父类型的构造函数中传递参数。
实例对象使用属性或方法的规则
实例对象使用的属性或方法,现在实例中查找,如果有则使用自身的属性或方法,
如果没有,则通过__proto__指向的原型对象 查找方法,找到则使用,
如果找不到则继续向__proto__寻找,直到未找到时报错
构造函数和原型对象和实例对象之间的关系
1.构造函数可以实例化对象
2.构造函数中有一个属性叫prototype,是构造函数的原型对象
3. 构造函数的原型对象(prototype)中有一个constructor 构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数
4. 实例对象的原型对象__proto__ 指向的是该构造函数的原型对象(prototype)
5. 构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问