再上一篇有简单讲过原型:JavaScript(5)--- 面向对象 + 原型javascript
讲原型链知识以前,先说几个重要的结论。html
一、原型链就是 对象的__proto__所链接的链状结构 二、prototype 属性是函数独有的 三、__proto__ 属性是对象独有的,实例原型(Object.prototype)也是对象,因此也会有__proto__属性
下面咱们一步一步来说解原型链java
咱们先使用构造函数建立一个对象:git
function Person() { } var p = new Person(); p.name = 'xiaoxiao'; console.log(p.name); //xiaoxiao
概念
它是 函数独有的属性,它从一个函数指向另外一个对象,表明这个对象是这个函数的原型对象,这个对象也是当前函数所建立的实例的原型对象。angularjs
prototype设计之初就是为了实现继承,让构造函数建立的全部实例,都可以共享这个原型属性和方法。github
有了prototype咱们不须要为每个实例建立重复的属性方法,而是将属性方法建立在构造函数的原型对象上(prototype)。那些不须要共享的才建立在构造函数中。面试
示例
函数
function Person(){ } Person.prototype.age=18; //原型属性 var p1 = new Person(); var p2 = new Person(); console.log(p1.age);//18 console.log(p2.age);//18
思考
这个函数的 prototype 属性到底指向的是什么呢?
其实,函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而建立的实例的原型 。
思考
那么什么是原型呢?.net
每个 JavaScript 对象 (null 除外 ) 在建立的时候就会与之关联另外一个对象,这个对象就是咱们所说的原型,每个对象都会从原型 ” 继承 ” 属性。prototype
这里p1和p2就是实例对象,而Person.prototype就是它们的原型对象。p1和p2能够去继承原型对象的方法和属性。
让咱们用一张图表示构造函数和实例原型之间的关系:
概念
__proto__属性是对象(包括函数,函数也是对象)独有的。__proto__属性是从一个对象指向另外一个对象,该属性指向的就是该对象的原型对象(也能够理解为父对象)。
示例
function Person(){ } var p = new Person(); console.log(p.__proto__ === Person.prototype);//true
更新下关系图
__proto__一般称为隐式原型,prototype为显示原型,那咱们能够说一个对象的隐式原型指向了该对象的构造函数的显示原型。那么咱们在显示原型上定义的属性方法,
经过隐式原型传递给了构造函数的实例。这样一来实例就能很容易的访问到构造函数原型上的方法和属性了。
概念
constructor是对象才有的属性,它是从一个对象指向一个函数的。指向的函数就是该对象的构造函数。
注意了 实例原型也是对象,因此也会有constructor属性,咱们来验证一下
function Person(){ } console.log(Person === Person.prototype.constructor);//true console.log(person.constructor); // ƒ Person(){}
再更新下关系图
总结 经过上面的演示说明,咱们能够得出
function Person(){ } var person = new Person(); console.log(person.__proto__ === Person.prototype);//true console.log(Person === Person.prototype.constructor);//true
了解了构造函数、实例原型、和实例之间的关系,接下来咱们讲讲实例和原型的关系
当读取实例的属性时,若是找不到,就会查找与对象关联的原型中的属性,若是还查不到,就去找原型的原型,一直找到最顶层为止。
示例
function Person(){ } var person = new Person(); Person.prototype.name='张三'; person.name='李四'; console.log(person.name);//李四 delete person.name; console.log(person.name);//张三
在这个例子中,咱们设置了 person 的 name 属性,因此咱们能够读取到为 ’李四’ ,当咱们删除了 person 的 name 属性时,读取 person.name ,从 person 中找不到
就会从 person 的原型中查找,name为 ’张三’ 。可是万一Person.prototype原型中尚未找到呢?那会到原型的原型去查找。也就是Object.prototype
示例
function Person(){ } var person = new Person(); Person.prototype.name='李四'; person.name='张三'; console.log(person.name);//张三 delete person.name; console.log(person.name);//李四 Object.prototype.name='obj'; delete Person.prototype.name; console.log(person.name);//obj
因此原型对象是经过 Object 构造函数生成的,结合以前所讲 , 实例的 _proto_ 指向构造函数的 prototype, 所
再更新下关系图
那 Object.prototypey也是对象,那它也应该会有原型。只不过有是有,只是为null
, 因此查到 Object.prototype 就能够中止查找了 。
因此最后一张关系图就是
总结
图中由相互关联的原型组成的链状结构就是原型链,也就是红色的这条线
。
一、JavaScript深刻之从原型到原型链 很是感谢
别人骂我胖,我会生气,由于我内心认可了我胖。别人说我矮,我就会以为可笑,由于我内心知道我不可能矮。这就是咱们为何会对别人的攻击生气。 攻我盾者,乃我心里之矛(3)。