为什么继承对象成员可以通过键访问但是“隐藏”?

时间:2015-10-02 14:02:52

标签: javascript inheritance

在玩JavaScript时(这对我来说很新),我发现了一些奇怪的行为:

var some_object = {
    foo: "bar",
    baz: "moo"
};

console.log(some_object); // { foo: 'bar', baz: 'moo' }

var inherited_object = Object.create(some_object);
console.log(inherited_object); // {} 
console.log(inherited_object.baz); // moo

继承的对象看起来是“空的”,但其成员仍然可以通过键访问。这里发生了什么以及这种行为背后的逻辑是什么?

4 个答案:

答案 0 :(得分:4)

这就是原型继承的工作原理。

使用Object.create从现有对象创建新对象时,属性将从创建对象的对象继承。因此,新创建的对象可能看起来是空的,但包含来自父级的继承属性的引用

继承对象的引用存储在对象的__proto__链接中,该链接包含对父对象属性的引用。

当您访问对象上的不存在的属性时,将搜索该属性的原型,如果未找到,则会搜索其父级,直到祖父级Object。如果在Object中找不到该属性,则返回错误/消息。

_____________              _____________              ______________
|Own Members|       -----> |     foo    |          -->| toString() |
|           |       |      |     bar    |          |  |  valueOf() |
|           |       |      |            |          |  |            |
|___________|       |      |____________|          |  |            |
| __proto__ |-------|      |  __proto__ |-----...--   |            |
-------------              --------------             --------------

inherited_obj              some_obj                       Object

请注意,除Object之外的所有对象都有原型链接。

原型链未被隐藏,您可以在__proto__属性中看到它。

答案 1 :(得分:3)

这是Javascript的原型链。每当您访问对象上的属性时,Javascript首先检查实际对象是否具有该属性,如果不是,则检查对象的原型是否具有该属性,如果不是 对象的原型具有该属性,等......

console.log将自身限制为直接输出中属性的“第一级”,但在现代Javascript控制台中,您通常可以单击并展开对象的__proto__以遍历链。

答案 2 :(得分:2)

这里发生了两件事:

  1. Object.create的工作原理

  2. 原型链如何运作。

  3. 理解Object.create实际上做什么是重要的

    Object.create这样做(有点):

    • 声明本地函数f
    • someobject 设置为其原型值(f.prototype = someobject
    • return new f

    inherited_object 有foo,bar。这就是你没看到它们的原因

    但是当你尝试搜索它们时,它无法在inherited_object中找到它,因此它会通过原型链。它找到了它。

答案 3 :(得分:1)

因为Object.create(...)使用some_object作为“inherited_object”的原型。这意味着如果你检查 inherited_object的结构,那么 __ proto __ 成员会指向 some_object

在javascript中如果未在对象中直接找到成员,则其原型正在搜索同一成员。因此,您将它们视为“隐藏”