先看一下什么是原型链
function Foo(){}
Foo.prototype.num = 3;
// new Foo( ) 将返回一个对象 把这个对象赋值给了 bar
var bar = new Foo();
// bar 是怎么找到的原型下面的num呢?
alert(bar.num); //3
bar并没有num 属性,它是怎么拿到3的呢 此处的 bar 就是通过原型链找到了值
原型链:
JavaScript中的对象有一个特殊的 __proto__
内置属性,其实此属性就是对于它的原型对象的引用(关联)。
当我们使用 function关键字声明一个函数时,系统会自动创建一个对象,访问这个对象可以通过 函数名.prototype 访问(我们一般把这个对象叫做原型对象)。
当使用 new 关键字调用函数时(这时我们一般把这个函数称为构造函数,关于使用new关键字执行的具体过程请阅读js 中的new(https://www.jianshu.com/p/9544f92572be))其中有一个步骤就是通过new关键字对function关键字什么函数时创建的对象进行原型关联,关联到声明函数时创建的那个对象(函数名.prototype指向的那个对象)。
上面例子 中使用 new 关键字调用 Foo()函数时会创建一个对象我们把这个对象赋值给了 bar ; bar对象内部的.__proto__
属性会关联到声明函数时创建的那个原型对象 , bar.num属性在bar中无法找到时,就会访问bar.__proto__
查找,这个过程会持续到找到匹配的属性名或者查找完整条prototype链(所有普通的[[Prototype]]链最终都会指向内置的Object.prototype)
,因此上面例子的原型链是这样的
bar.__proto__ -- 指向 --> Foo.prototype --然后(Foo.prototype.__proto__) -- 指向 --> Object.prototype
使用图表示
并且每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针(constructor),而实例都包含一个指向原型对象的内部指针( __proto__
)。
那么,假如我们让原型对象等于另一个类型的实例,结果会怎么样呢?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条。这就是所谓原型链的基本概念
对prototype更详细的介绍请看这里(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype)
补充:
function People(name) {
this.name = name;
this.sayName = function() {
console.log('my name is:' + this.name);
}
}
People.prototype.walk = function() {
console.log(this.name + 'is walking');
}
var p1 = new People('饥人谷');
var p2 = new People('前端');
以下三点需要谨记
1.每个对象都具有一个名为_proto_的属性;
2.每个构造函数(构造函数标准为大写开头,如Function(),Object()等等JS中自带的构造函数,以及自己创建的)都具有一个名为prototype的属性,指向一个对象
3.每个对象的_proto_属性指向自身构造函数的prototype 指向的对象;
https://segmentfault.com/a/1190000011880268