前言:JavaScript 使用原型继承,这意味着一个对象可以有(通常确实有)它背后的原型,也就是另一个对象。如果您尝试从对象中获取属性的值,而该对象不具有该属性的值,则 JavaScript 引擎会查找该对象的原型(及其原型等)以找到它。
Object.create
创建对象。您给出的第一个参数Object.create
是用作它创建的对象的原型的对象。所以:
// Create an object with a property 'foo'
var a = {
foo: 42
};
// Create a blank object using `a` as its prototype
var b = Object.create(a);
// Give `b` a property of its own
b.bar = "hi";
这让我们记忆犹新:
+−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−+
| [[原型]] |−−−−−>| (标准 |
a−−−−−−−−−−−−−−−−−−−−−−−+−−>| 富:42 | | 对象原型)|
| +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−+
|
+−−−−−−−−−−−−−−−−+ |
b−−>| [[原型]] |−−+
| 酒吧:“嗨”|
+−−−−−−−−−−−−−−−−−+
证明b
用途a
:
console.log(b.foo); // 42
a.foo = 67;
console.log(b.foo); // 67
解决您的一些变化:
var o = Object.create(Object.prototype);
这与 完全相同var o = {};
:它创建一个新的空白对象,其原型是对象Object.prototype
引用。
var o = Object.create(Object);
这将创建一个新的空白对象o
,其原型是Object
函数。它不创建函数,只是一个以函数为原型的非函数对象。这会很奇怪,可能不是你想要的。:-)
var o = Object.create(null);
创建一个o
原型为的新空白对象null
。由于它的原型是null
,它没有通常的Object.prototype
东西,比如toString
andvalueOf
和hasOwnProperty
。这有点不寻常,尽管它有一些用例,例如当您将对象用作字典/映射并且不希望这些属性名称出现误报时。(在 ES2015 [aka ES6] 中,另一个选项是使用Map
。)
正如 thg435 在下面的评论中指出的那样,关于 JavaScript 的一个令人困惑的事情是对象的原型与prototype
您在函数上看到的属性完全不同。如果该prototype
属性有一个不同的名称可能会更好(尽管我无法想象它会是什么名称而不是非常笨重)。
一个对象(我们称之为o
)有一个原型对象,它继承了它的属性。(在 ES2015+ 中,您可以通过 访问该对象Object.getPrototypeOf
。)prototype
函数属性上的对象根本不一定是任何对象的原型。相反,它将被new
分配为通过使用该函数创建的任何对象的原型的对象。
示例在这里有所帮助。
function Foo() {
}
该函数Foo
具有Foo.prototype
引用对象的属性。该对象尚未用作任何东西的原型。它只是分配给prototype
在Foo
对象实例上调用的属性的对象。
var f = new Foo();
现在该对象被用作原型,具体来说,它是调用f
创建的对象的原型new Foo
。
忽略一些细节,这行代码:
var f = new Foo();
...基本上是这样做的:
// Create a blank object, giving it `Foo.prototype` as its prototype
var f = Object.create(Foo.prototype);
// Call` Foo` using that new object as `this`
Foo.call(f);
正如我所说,这遗漏了一些细节,但希望它有助于弄清楚prototype
函数的属性是什么......