JS 原型链图形详解
JS原型链
这篇文章是「深入ECMA-262-3」系列的一个概览和摘要。每个部分都包含了对应章节的链接,所以你可以阅读它们以便对其有更深的理解。
对象
ECMAScript做为一个高度抽象的面向对象语言,是通过对象来交互的。即使ECMAScript里边也有基本类型,但是,当需要的时候,它们也会被转换成对象。
一个对象就是一个属性集合,并拥有一个独立的prototype(原型)对象。这个prototype可以是一个对象或者null。*
让我们看一个关于对象的基本例子。一个对象的prototype是以内部的[[Prototype]]属性来引用的。但是,在示意图里边我们将会使用__<internal-property>__下划线标记来替代两个括号,对于prototype对象来说是:__proto__\。
对于以下代码:
这些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); //
c.calculate(40); //
规则很简单:如果一个属性或者一个方法在对象自身中无法找到(也就是对象自身没有一个那样的属性),然后它会尝试在原型链中寻找这个属性/方法。如果这个属性在原型中没有查找到,那么将会查找这个原型的原型,以此类推,遍历整个原型链(当然这在类继承中也是一样的,当解析一个继承的方法的时候-我们遍历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}});
你可以在对应的章节获取到更多关于ES5新API的信息。 ES6标准化了 __proto__属性,并且可以在对象初始化的时候使用它。
通常情况下需要对象拥有相同或者相似的状态结构(也就是相同的属性集合),赋以不同的状态值。在这个情况下我们可能需要使用构造函数(constructorfunction),其以指定的模式来创造对象。
构造函数
除了以指定模式创建对象之外,构造函数也做了另一个有用的事情-它自动地为新创建的对象设置一个原型对象。这个原型对象存储在ConstructorFunction.prototype属性中。
换句话说,我们可以使用构造函数来重写上一个拥有对象b和对象c的例子。因此,对象a(一个原型对象)的角色由Foo.prototype来扮演:
// a constructor function
function Foo(y) {
this.y = y;
}
Foo.prototype.x = 10;
Foo.prototype.calculate = function (z) {
return this.x + this.y + z;
}; var b = new Foo(20);
var c = new Foo(30);
// 调用继承方法
b.calculate(30); //
c.calculate(40); //
console.log( b.__proto__ === Foo.prototype) // true
console.log(c.__proto__ === Foo.prototype) // true //同时 Foo.prototype 同时会创建一个特殊的属性 constructor,
b.constructor === Foo // true
c.constructor === Foo, // true
Foo.prototype.constructor === Foo // true
b.calculate === b.__proto__.calculate // true
b.__proto__.calculate === Foo.prototype.calculate // true
这个代码可以表示为如下关系:
正式来说,如果思考一下分类的概念(并且我们已经对Foo进行了分类),那么构造函数和原型对象合在一起可以叫作「类」。实际上,举个例子,Python的第一级(first-class)动态类(dynamic classes)显然是以同样的属性/方法处理方案来实现的。从这个角度来说,Python中的类就是ECMAScript使用的委托继承的一个语法糖。
注意: 在ES6中「类」的概念被标准化了,并且实际上以一种构建在构造函数上面的语法糖来实现,就像上面描述的一样。从这个角度来看原型链成为了类继承的一种具体实现方式:
// ES6 class Foo { constructor(name) {
this._name = name;
}
getName {
return this._name;
}
}
class Bar extends Foo {
getName {
return super.getName + ' Doe';
}
}
var bar = newBar('John');
console.log(bar.getName); // John Doe
转自JavaScript. The core.
http://www.yidianzixun.com/n/0CjThYEE?s=9&appid=xiaomi&ver=3.5.5&utk=03smxf0g
JS 原型链图形详解的更多相关文章
- 最详尽的 JS 原型与原型链终极详解,没有「可能是」。(一)
最详尽的 JS 原型与原型链终极详解,没有「可能是」.(一) 第二篇已更新,点击进入第三篇已更新,点击进入
- JS原型与原型链终极详解(转)
JavaScript原型及原型链详解 一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的.分为普通对象和函数对象,Object,Function 是JS自带的函数对象. ...
- 【repost】JS原型与原型链终极详解
一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的.分为普通对象和函数对象,Object ,Function 是JS自带的函数对象.下面举例说明 function f ...
- JS原型与原型链终极详解
一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的.分为普通对象和函数对象,Object ,Function 是JS自带的函数对象.下面举例说明 function f ...
- js重点--原型链继承详解
上篇说过了关于原型链继承的问题,这篇详解一下. 1. function animals(){ this.type = "animals"; } animals.prototype. ...
- [转] 最详尽的 JS 原型与原型链终极详解
四. __proto__ JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__ 的内置属性,用于指向创建它的构造函数的原型对象. 对象 person1 有一个 __pr ...
- JS原型与原型链终极详解 (转载)
这篇文章需要认认真真仔仔细细的看才能看懂 一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的.分为普通对象和函数对象,Object ,Function 是JS自带的函 ...
- JS 原型与原型链终极详解(二)
四. __proto__ JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__ 的内置属性,用于指向创建它的构造函数的原型对象. 对象 person1 有一个 __pr ...
- 最详尽的 JS 原型与原型链终极详解(1)(2)(3)===转载
转载===方便以后复习 原文网址:https://www.jianshu.com/p/dee9f8b14771 一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的.分为 ...
随机推荐
- MediaPlayer简单使用,绑定surfaceView实现播放视频的功能
转载自 Android MediaPlayer使用方法简单介绍 播放音频 android中播放音频可以使用MediaPlayer类来实现,一下是它的一些方法: 方法名 功能描述 setDataSour ...
- 安装tomcat 证书
创建证书keystore 1) Mdmc用户登录服务器,执行如下命令: keytool -genkey -v -alias tomcat -keyalg RSA -keystore tomc ...
- find & rm
1)查找并删除3天前的历史文件 rm -rfi `find /tmp/ -ctime 3` 2)按分钟查找 find -cmin N
- C#打开指定目录,并将焦点放在指定文件上。相对路径(程序起动的目录)
string basepath = AppDomain.CurrentDomain.BaseDirectory; string filepath = "logs\\Log.log" ...
- 在vs中跑动kdtree 和 bbf
这两天的学习模型都来自:http://blog.csdn.net/masibuaa/article/details/9246493 所谓的bbf 英文名字叫做best bin first 译名:最优节 ...
- 打印W图案
一:规律 二维图形的展示都可以使用二维数组来解决,W图形x轴0,1,2,1,0,1,2.....在0到2直接来回的徘徊 y轴是在一直递增........ 二:代码 @Test /** * 测试打印w图 ...
- 【数论,水题】UVa 11728 - Alternate Task
题目链接 题意:给出一个数S,求一个最大的数,使这个数所有的因子之和为S; 这个所谓“因子之和”不知道有没有误导性,因为一开始以为得是素数才行.后来复习了下小学数学,比如12的因子分别是1,2,3,4 ...
- button倒计时可点击
- sharepoint 中用自带的download.aspx实现文件的下载,中文文件名编码的问题
]中的路径绑定的是下载路径,用到了sharepoint中自带的download.aspx下载页面,只要将文件的URL赋值给sourceurl即可,但是我前台用的是<a>标签的href来导向 ...
- Https要点
http和https的区别 1.https协议需要到ca申请证书 2.http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议 3.http和https使用的是完全不同 ...