在玩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
继承的对象看起来是“空的”,但其成员仍然可以通过键访问。这里发生了什么以及这种行为背后的逻辑是什么?
答案 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)
这里发生了两件事:
Object.create的工作原理
原型链如何运作。
理解Object.create实际上做什么是重要的。
Object.create
这样做(有点):
f
someobject
设置为其原型值(f.prototype = someobject
)new f
inherited_object
不有foo,bar。这就是你没看到它们的原因
但是当你尝试搜索它们时,它无法在inherited_object
中找到它,因此它会通过原型链。它找到了它。
答案 3 :(得分:1)
因为Object.create(...)使用some_object作为“inherited_object”的原型。这意味着如果你检查 inherited_object的结构,那么 __ proto __ 成员会指向 some_object 。
在javascript中如果未在对象中直接找到成员,则其原型正在搜索同一成员。因此,您将它们视为“隐藏”