javascript - Prototype Chain - 本例中使用的是原型(prototype)链吗?

标签 javascript

我正在关注 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't Bar.prototype now reference a new object which is a copy of Foo.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/

相关文章:

javascript - 使用 localhost 作为 http 代理

Javascript 对标题数组进行排序的方式与根据数据数组的排序方式相同

javascript - 在 redux 中使用生命周期方法与在 render 方法中检查 prop 状态

javascript - 使用 Azure Functions Core Tools 时如何解决 'Value cannot be null' 错误?

javascript - Sunburst 分区数据被同一页上的第二个 sunburst 覆盖

javascript - 区分折线图和柱形图类型之间的边界

javascript - 为什么 window.foo 未定义而调用 foo 会引发错误?

javascript - 如何在 Node js中包装长sql语句

javascript - 有没有办法在 fetch 调用后渲染 js.erb ?

javascript - Jquery/Ajax 通过 ID 更新 Span 或 Div 而无需刷新页面