javascript-Object.create解释
我对以下canonical object.create方法有疑问:javascript-Object.create解释,javascript,object-create,Javascript,Object Create,我对以下canonical object.create方法有疑问: Object.create = function(o, props) { function F() {} F.prototype = o; if (typeof(props) === "object") { for (prop in props) { if (props.hasOwnProperty((prop))) { F[prop] = props[prop];
Object.create = function(o, props) {
function F() {}
F.prototype = o;
if (typeof(props) === "object") {
for (prop in props) {
if (props.hasOwnProperty((prop))) {
F[prop] = props[prop];
}
}
}
return new F();
};
在上面代码的第3行,我们将F对象的prototype属性设置为o参数的prototype
我认为这意味着o和F都指向同一个原型,因此指向同一组成员
但是代码随后继续复制prop-in-props循环中的所有成员
如果我们接着手动复制所有成员,那么在第3行中设置原型有什么意义?将
F
视为一个函数,它返回一个对象的新实例,并F.prototype
引用新实例从中借用属性的对象
使用F
创建的实例具有独立于F.prototype
的自己的属性集
当在F
的白炽灯中找不到属性时,运行时将加快原型链并查看F.prototype
中是否存在该属性
这就是为什么您希望复制一些并继承其他
原型的要点是提供类似类的代码重用/属性存储
将
F.prototype
视为F
的类实例作为对象。您提供的代码与ECMA标准定义的object.create()
不同。第二个参数(这里称为prop
)的成员应该是在结果对象上定义的一组描述符,而不是复制到构造函数中。这更准确(但也不完全正确)
props
参数包含新对象成员的属性描述符,您希望这些成员不同于原型中指定的o
。这些值不应该被逐字复制到对象中,而应该像调用对象一样进行处理。defineProperties()
,上面通过将描述符的值
部分指定给新对象来模拟Object.create()
无法精确地填充到ECMA 3中,因为它可以用于指定具有访问器函数的属性,尽管上述操作适用于使用value
而不是get
或set
的道具
如果您对polyfill版本不感兴趣,下面将准确描述对象.create()
的功能,假设\uuuuuuuuuuuu
和对象.defineProperties()
都存在
对象的版本有错误。在您的问题中,create
:循环将属性附加到构造函数F
(而不是返回的对象或其原型),这意味着它们在创建的对象中不可访问
Object.create
的第二个参数的属性应该复制到新创建的对象。政府是这样说的:
如果已指定但未定义,则其可枚举属性(即在其自身上定义的属性,而不是其原型链上的可枚举属性)的对象将指定要添加到新创建对象的属性描述符以及相应的属性名称
尝试使用对象的版本运行以下代码。在问题中创建:
o = Object.create(
{a: "prototype's a", b: "prototype's b"},
{a: "object's a"}
);
你会发现o.a==“prototype's a”
和o.b==“prototype's b”
,“object's a”
丢失了
以下版本的函数可能更有用:
Object.create = function(o, props) {
var newObj;
// Create a constructor function, using o as the prototype
function F() {}
F.prototype = o;
// Create a new object using F as the constructor function
newObj = new F();
// Attach the properties of props to the new object
if (typeof(props) === "object") {
for (prop in props) {
if (props.hasOwnProperty((prop))) {
newObj[prop] = props[prop];
}
}
}
return newObj;
};
让我们用同样的例子来尝试一下:
o = Object.create(
{a: "prototype's a", b: "prototype's b"},
{a: "object's a"}
);
新对象o
是使用具有属性a
和b
及其自身属性a
的原型创建的
让我们先看看o.b
:o.hasOwnProperty(“b”)
将返回false
,因为o
没有名为b
的属性。这就是原型出现的地方;因为没有属性b
,所以会在原型上查找它,因此o.b==“原型的b”
另一方面,o.hasOwnProperty(“a”)
将返回true
,因为o
确实具有a
属性o.a==“对象的a”
并且没有从原型中查找任何内容
正如中所指出的,Object.create
的正确实现比这更复杂。有关更多详细信息,请参见。-1:F
从不从F.prototype
借用属性,使用new F()创建的对象从F.prototype
借用属性,以指出对象.create
确实比我在回答中给出的简单版本复杂得多。
Object.create = function(o, props) {
var newObj;
// Create a constructor function, using o as the prototype
function F() {}
F.prototype = o;
// Create a new object using F as the constructor function
newObj = new F();
// Attach the properties of props to the new object
if (typeof(props) === "object") {
for (prop in props) {
if (props.hasOwnProperty((prop))) {
newObj[prop] = props[prop];
}
}
}
return newObj;
};
o = Object.create(
{a: "prototype's a", b: "prototype's b"},
{a: "object's a"}
);