javascript-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];

我对以下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];
      }
     }
    }
    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"}
    );