一个对象就是一个属性集合,并拥有一个独立的prototype(原型)对象。这个prototype可以是一个对象或 者null。

一个对象的prototype是以内部的[[Prototype]]属性来引用的。但是,在示意图里边 我们将会使用__<internal-property>__下划线标记来替代两个括号,对于prototype对象来说是:__proto__。

对于以下代码:

var foo = {

  x: 10,

  y: 20

};

我们拥有一个这样的结构,两个明显的自身属性和一个隐含的__proto__属性,这个属性是对foo原型对象的引用:

这些prototype有什么用?让我们以原型链(prototype chain)的概念来回答这个问题。

原型对象也是简单的对象并且可以拥有它们自己的原型。如果一个原型对象的原型是一个非null的引用,那么以此类 推,这就叫作原型链。

原型链是一个用来实现继承和共享属性的有限对象链。

考虑这么一个情况,我们拥有两个对象,它们之间只有一小部分不同,其他部分都相同。显然,对于一个设计良好的 系统,我们将会重用相似的功能/代码,而不是在每个单独的对象中重复它。在基于类的系统中,这个代码重用风格叫 作类继承-你把相似的功能放入类A中,然后类 B和类 C继承类 A,并且拥有它们自己的一些小的额外变动。

ECMAScript中没有类的概念。但是,代码重用的风格并没有太多不同(尽管从某些方面来说比基于类(class-based) 的方式要更加灵活)并且通过原型链来实现。这种继承方式叫作委托继承(delegation based inheritance)(或者,更贴 近ECMAScript一些,叫作原型继承(prototype based inheritance))。

跟例子中的类A,B,C相似,在ECMAScript中你创建对象:a,b,c。于是,对象a中存储对象b和c中通用的部分。然 后b和c只存储它们自身的额外属性或者方法。

var a = { x: 10, calculate: function (z) { return this.x + this.y + z } };
var b = { y: 20, __proto__: a };
var c = { y: 30, __proto__: a };
// call the inherited method b.calculate(30); // 60 c.calculate(40); // 80

我们看到b和c访问到了在对象a中定义的calculate方法。这是通过原型链实现的。

规则很简单:如果一个属性或者一个方法在对象自身中无法找到(也就是对象自身没有一个那样的属性),然后它会 尝试在原型链中寻找这个属性/方法,

如果这个属性在原型中没有查找到,那么将会查找这个原型的原型,以此类推, 遍历整个原型链(当然这在类继承中也是一样的,当解析一个继承的方法的时候-我们遍历class链( class chain))。第一个被查找到的同名属性/方法会被使用。因此,一个被查找到的属性叫作继承属性。如果在遍历了整个 原型链之后还是没有查找到这个属性的话,返回undefined值。
注意,继承方法中所使用的this的值被设置为原始对象,而并不是在其中查找到这个方法的(原型)对象。也就是, 在上面的例子中this.y取的是b和c中的值,而不是a中的值。但是,this.x是取的是a中的值,并且又一次通过原型 链机制完成。

如果没有明确为一个对象指定原型,那么它将会使用__proto__的默认值 -Object.prototype。Object.prototype对象自身也有一个__proto__属性,这是原型链的终点并且值为null。
下一张图展示了对象a,b,c之间的继承层级:

注意: ES5标准化了一个实现原型继承的可选方法,即使用Object.create函数:

var b = Object.create(a, {y: {value: 20}});

var c = Object.create(a, {y: {value: 30}});

最新文章

  1. 一个nginx匹配很诡异的问题
  2. 虚拟机中Linux系统盘空间不足
  3. sed 使用 删除匹配行
  4. JavaWeb之 JSP:自定义标签
  5. truncate、drop、delete区别
  6. linux 压缩/解压命令大全
  7. uEditor独立图片上传
  8. think straight系列读书笔记之《暗时间》
  9. 比较优势 - MBA智库百科
  10. HDU 1540 POJ 2892 Tunnel Warfare
  11. ios数据存储——对象归档
  12. C# Winform中的窗体传值
  13. Kindeditor编辑插件的使用
  14. SQL随记(二)
  15. 理解 vue-router的beforeEach无限循环的问题
  16. BZOJ4675
  17. 【webssh】网页上的SSH终端
  18. 在AJAX里 使用【 JSON 】 返回数据类型 实现简单的下拉菜单数据
  19. &#39;org.springframework.web.filter.CharacterEncodingFilter&#39; is not assignable to &#39;javax.servlet.Filter,This inspection lets you spot the following problems that might occur in descriptors that are used t
  20. arcgis runtime 100 Create geometries

热门文章

  1. [批处理] Git中log的使用
  2. mysql索引类型(按存储结构划分)
  3. css3 样式过度器 Transition
  4. SynchronousQueueDemo
  5. qemu创建vm和vcpu进入kvm的流程
  6. c# 将CSV文件转成list集合
  7. Java基础总结1
  8. latch
  9. 14: linux实用命令
  10. springBoot整合jpa