开源中国

我们不支持 IE 10 及以下版本浏览器

It appears you’re using an unsupported browser

为了获得更好的浏览体验,我们强烈建议您使用较新版本的 Chrome、 Firefox、 Safari 等,或者升级到最新版本的IE浏览器。 如果您使用的是 IE 11 或以上版本,请关闭“兼容性视图”。
理解 Javascript 的原型概念 - 技术翻译 - 开源中国社区

理解 Javascript 的原型概念 【已翻译100%】

苗哥 推荐于 4年前 (共 17 段, 翻译完成于 01-07) 评论 5
收藏  
21
推荐标签: JavaScript 待读

JavaScript 的原型对象总是让人纠结。即使是经验丰富的JavaScript专家甚至其作者,经常对这一概念给出很有限的解释。我相信问题来自于我们对原型最早的认识。原型总是与new, constructor 以及令人困惑的prototype属性紧密联系。事实上,原型是一个相当简单的概念。为了更好地理解它,我们需要忘记我们所‘学到’的构造原型,然后,追本溯源。

Cloud_Lee
 翻译得不错哦!

什么是原型?

原型是一个从其他对象继承属性的对象。

是不是任何对象都可以是原型?

是的

那些对象有原型?

每个对象都有一个默认的原型。原型本身就是对象,每一个原型本身也存在一个原型。(只有一个例外,默认的对象原型在每条原型链的顶端,其他的原型在原型链的后面)

 

without1943
 翻译得不错哦!

退一步说,什么又是对象呢?

在JavaScript中一个对象是以键值对保存的任意的无序集合,如果它不是原始类(undefined,null,boolean.nuber或string),它就是一个对象

maosi
 翻译得不错哦!
你可以认为每个对象都有一个prototype. 但当我写({}).prototype的时候,我却得到了undefined,你疯不疯?

忘记你所掌握的关于prototype属性的理解 - 这很可能是迷惑的根源. 一个对象真正的prototype是内部[[Prototype]]属性. ECMA 5介绍了标准的访问方法,Object.getPrototypeOf(object)。这个最新的实现已被Firefox, Safari, Chrome and IE9所支持. 另外,除了IE,所有的浏览器都支持非标准的访问方法__proto__.不然的话,我们只能说对象的构造方法就是它的prototype属性.


var a = {};

//Opera 或 IE<=8下失败
Object.getPrototypeOf(a); //[object Object]

//IE下失败
a.__proto__; //[object Object]

//所有浏览器
//(but only if constructor.prototype has not been replaced and fails with Object.create)
a.constructor.prototype; //[object Object]



恺哥
 翻译得不错哦!

很好, false 是原始类型, 为什么false.__proto__ 会返回一个值呢?

当访问原始类型的原型(prototype),它会强制转化为一个对象。

//(works in IE<=8 too, due to double-negative)
false.__proto__ === Boolean(false).__proto__; //true

我想使用原型实现继承,我现在该怎么做?

给一个实例添加原型属性,几乎是没有意义的.除非一种情况,那就是,很有效率的添加属性直接到实例本身.假设我们已经有了一个对象,要共享已经存在的对象的功能.例如Array,我们可以这样做

//fails in IE<=8
var a = {};
a.__proto_ = Array.prototype;
a.length; //0



Marix
 翻译得不错哦!
但是我们可以看到原型的真正强大在于多个实例共享同一原型。原型对象的属性只被定义一次就可以被它引用的所有实例所继承。使用原型对性能和程序可维护性的提高效果是很显而易见的。那么这就是构造函数产生的原因吗?是的,构造函数提供了一个便捷的跨浏览器机制来实现对实例创建时的公用原型分配。。
阿莫斯
 翻译得不错哦!

在给出一个例子之前,我需要知道constructor.prototype property是干什么的?

好吧,首先,JavaScript不区分构造函数和其它方法,所以每个方法都有prototype属性。反而任何不是方法的,都没有这样的属性。

//永远不是构造函数的方法,无论如何都是有prototype属性的
Math.max.prototype; //[object Object]

//构造函数也有prototype属性
var A = function(name) {
	this.name = name;
}
A.prototype; //[object Object]

//Math不是一个方法,所以没有prototype属性
Math.prototype; //null



Jiang Hongfei
 翻译得不错哦!
现在可以定义: 一个方法的prototype属性是当这个方法被用作构造函数来创建实例时赋给该实例的prototype的对象。

非常重要的一点是,要理解方法的prototype属性和实际的prototype没有任何关系。

//(在IE中会失败)
var A = function(name) {
	this.name = name;
}

A.prototype == A.__proto__; //false
A.__proto__ == Function.prototype; //true - A的prototype是它的构造函数的prototype属性


Jiang Hongfei
 翻译得不错哦!

能给个例子不?

以下的代码,可能你已经看到或用过上百次了,但这里又把它搬上来了,但可能会有些新意。

//构造器. <em>this</em> 作为新对象返回并且它内部的[[prototype]]属性将被设置为构造器默认的prototype属性
var Circle = function(radius) {
    this.radius = radius;
    //next line is implicit, added for illustration only
    //this.__proto__ = Circle.prototype;
}

//扩充 Circle默认的prototype对象的属性因此扩充了每个由它新建实例的prototype对象的属性
Circle.prototype.area = function() {
   return Math.PI*this.radius*this.radius;
}

//创建Circle的两个示例,每个都会使用相同的prototype属性
var a = new Circle(3), b = new Circle(4);
a.area().toFixed(2); //28.27
b.area().toFixed(2); //50.27

这很棒。如果我改变了constructor的prototype属性,即使是已存在的实例对象也可以立刻访问新的prototype版本吗?

嗯......不完全是。如果我修改的是现存prototype的属性后,那么确实是这种情况,因为对象创建时a.__proto__引用了A.prototype所定义的对象。

var A = function(name) {
    this.name = name;
}

var a = new A('alpha');
a.name; //'alpha'

A.prototype.x = 23;

a.x; //23
big军
 翻译得不错哦!

但是如果我将prototype属性用一个新对象代替,a.__proto__ 仍然指向原始对象。

var A = function(name) {
    this.name = name;
}

var a = new A('alpha');
a.name; //'alpha'

A.prototype = {x:23};

a.x; //null

一个缺省的prototype是什么样的?

一个拥有constructor属性的对象。

var A = function() {};
A.prototype.constructor == A; //true

var a = new A();
a.constructor == A; //true (a 的constructor属性继承自它的原型)

Cloud_Lee
 翻译得不错哦!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们
评论(5)
Ctrl/CMD+Enter

看完这篇文章后 脑袋更大了 ~
http://wenku.baidu.com/view/059c7c6b561252d380eb6e72.html 还是这个奖的更通俗易懂
这篇文章确实让人迷糊

还是挺有启发的,这是我的总结:
https://github.com/yangjunjun/blog/issues/7

本来有点思路,看完懵了.

顶部