我正在关注 Kyle Simpson 的 YouDontKnowJS frontendmasters.com并且对他的一个例子感到困惑。
示例代码如下:
function Foo(who){
this.me = who;
}
Foo.prototype.identify = function() {
return "I am " + this.me;
};
function Bar(who) {
Foo.call(this, who);
}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.speak = function() {
alert("Hello, " + this.identify() + ".");
}
var b1 = new Bar("b1");
var b2 = new Bar("b2");
b1.speak();
b2.speak();
当调用 new Bar("b1")
时;他将带您了解调用 b1.speak() 时原型(prototype)链发生的情况
- 在
Bar.prototype
上调用了 alert 函数,也调用了 this.identify()。 - 当调用 this.identify() 时,在
this
对象 (b1) 中找不到它,因此它查找它的原型(prototype)。 - 查看
Bar.prototype
它没有找到 identify 方法,所以它再次查找它的原型(prototype)链。 - 它现在在
Foo.prototype
上找到识别方法
这是我不清楚的地方。当我们调用 Bar.prototype = Object.create(Foo.prototype)
时,Bar.prototype
现在不应该引用一个新对象,它是 Foo 的副本.prototype
,上面有 identify()
方法?为什么它必须在原型(prototype)链中向上一级到 Foo.prototype
才能找到 identify()
方法?
文档中Object.create()
的官方定义:
The Object.create() method creates a new object with the specified prototype object and properties
最佳答案
When we call
Bar.prototype = Object.create(Foo.prototype)
, shouldn'tBar.prototype
now reference a new object which is a copy ofFoo.prototype
...
Object.create
不会复制 对象。它创建了一个新对象,其底层原型(prototype)是我们传入的。所以从这个开始:
+---------------+ | Foo.prototype | +---------------+ +----------------------+ | [[Prototype]] |---->| Object.prototype | +---------------+ +----------------------+ | identify: ... | | [[Prototype]]: null | +---------------+ +----------------------+ | ... | +----------------------+
(为简单起见,我省略了 identify
的函数对象。)
...当我们执行 Bar.prototype = Object.create(Foo.prototype)
时,它创建了这个:
+---------------+ | Bar.prototype | +---------------+ +---------------+ | [[Prototype]] |---->| Foo.prototype | +---------------+ +---------------+ +----------------------+ | [[Prototype]] |---->| Object.prototype | +---------------+ +----------------------+ | identify: ... | | [[Prototype]]: null | +---------------+ +----------------------+ | ... | +----------------------+
稍后,在 Bar.prototype.speak = function...
行执行后,Bar.prototype
也有 speak
属性.
+---------------+ | Bar.prototype | +---------------+ +---------------+ | [[Prototype]] |---->| Foo.prototype | +---------------+ +---------------+ +----------------------+ | speak: ... | | [[Prototype]] |---->| Object.prototype | +---------------+ +---------------+ +----------------------+ | identify: ... | | [[Prototype]]: null | +---------------+ +----------------------+ | ... | +----------------------+
在 var b1 = new Bar("b1");
之后,我们有:
+---------------+ | b1 | +---------------+ +---------------+ | [[Prototype]] |---->| Bar.prototype | +---------------+ +---------------+ +---------------+ | me: "b1" | | [[Prototype]] |---->| Foo.prototype | +---------------+ +---------------+ +---------------+ +----------------------+ | speak: ... | | [[Prototype]] |---->| Object.prototype | +---------------+ +---------------+ +----------------------+ | identify: ... | | [[Prototype]]: null | +---------------+ +----------------------+ | ... | +----------------------+
[在上面,[[Prototype]]
指的是对象到其原型(prototype)的内置链接;对象上实际上没有名为 [[Prototype]]
的属性。
事实上,在 ES5 中没有办法从对象本身直接访问原型(prototype)的链接,尽管 ES5 添加了 Object.getPrototypeOf
允许您通过传入对象引用来检索它,例如var p = Object.getPrototypeOf(someObject)
。 ES6 将添加更多与对象原型(prototype)交互的方式,包括 Mozilla 的 JavaScript 多年来一直拥有的 __proto__
属性。]
关于javascript - Prototype Chain - 本例中使用的是原型(prototype)链吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26087232/