在开始讲原型和原型链以前,咱们先确认如下几个概念:git
先知道以上3点,下面咱们一步一步来讲明:github
第一步:咱们建立一个构造函数Personsegmentfault
function Person(name){
this.name = name; // 属性name
this.sayHello = function(){ // 方法sayHello
console.log(name + 'say hello');
}
}复制代码
如今建立一个实例对象moose并传入名字“moose”数组
var moose = new Person('moose');复制代码
这时候咱们来打印一下,看看moose是否是拥有Person的属性和方法浏览器
moose.sayHello(); // moose say hello复制代码
咱们知道moose这个对象在建立的时候并无直接建立sayHello()方法,即便你们知道从Person中继承过来的,那究竟是怎么实现的呢?这就是咱们接下来要讲的原型和原型链。bash
在Person这个构造函数定义的时候,同时建立的还有一个与之关联的“原型对象”,这个对象毕竟不是咱们手动建立命名的一个对象,那要使用这个“原型对象”怎么办呢?JS提供了一个属性“prototype”给函数。Person.prototype就指向这个“原型对象”。函数
这个时候咱们经过Person这个构造函数建立了一个实例对象“moose”,要想实现继承这样一个关系,moose必须可以使用Person中的属性和方法。JS的作法是给实例对象提供了一个"__proto__"的属性,moose.__proto__也指向Person对应的这个实例对象。这样咱们就得出了一个小结论:this
console.log(Person.prototype === moose.__proto__); // true复制代码
到目前为止,原型链继承就实现了。spa
第一步原型关系图以下:prototype
第二步:既然实例对象和构造函数均可以指向原型,那么原型是否有属性指向构造函数或者实例呢?
很遗憾,原型没有指向实例对象的属性,可是指向构造函数的有啊~:constructor登场
console.log(Person === Person.prototype.constructor); // true复制代码
既然说了原型相关的概念,咱们不妨在说一下原型链,简单的说,原型链就是一条由一堆上下等级分明的原型组成的继承链。
第三步:就上面的例子而言:moose经过__proto__找到本身的原型,继承原型对应函数的属性和方法。那么咱们难想到,原型对象自己就是一个对象呀,也拥有__proto__属性,那么它的原型又会是什么呢?
console.log(Person.prototype);复制代码
console.log(Person.prototype.__proto__ === Object.prototype); // true复制代码
从浏览器中打印出的结果页能够看到,Object.prototype原型的constructor属性指向的是Object函数。
那么Object.prototype的原型又是什么呢?
console.log(Object.prototype.__proto__); // null复制代码
这就说明Object.prototype 已经没有原型了,Object对象是根对象。
以上一整个查找原型的过程走的就是这样一条清晰的原型链。
拓展问题:instanceof原理是什么?
// 咱们以数组为例
var arr = []
arr instanceof Array复制代码
instanceof原理就是利用了原型链,当执行arr instanceof Array时,会从arr的_proto_一层一层往上找,看是否能不能找到Array的prototype。
咱们知道var arr = [] 实际上是var arr = new Array()的语法糖,因此arr的_proto_指向Array的prototype,结果返回true
到此为止,咱们大致的梳理了一下原型以及原型链相关的内容
特别感谢提供相关内容参考:
附:感谢您的阅读,但愿对您有所帮助。若是以上内容中存在疑问和错误,欢迎留言或者私信。