【问题标题】:Difference between Object.create(Parent.prototype) vs Object.create(Parent) during prototype inheritance原型继承期间 Object.create(Parent.prototype) 与 Object.create(Parent) 之间的区别
【发布时间】:2019-01-25 07:59:13
【问题描述】:

在典型的 JavaScript 继承中,我们将 Parent.prototype 传递给 Object.create。

function Parent() {};

function Child() {
    Parent.call(this);
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var foo = new Child();

调用 Object.create(Person) 和 Object.create(Parent.prototype) 有区别吗?

包括下面链接的 MDN 文章在内的许多教程都传递了“Parent.prototype”,而不仅仅是“Parent”。

根据MDN 定义“Object.create() 方法创建一个新对象,使用现有对象作为新创建对象的原型。”

我尝试了两种方法,console.log 显示两种方法的结果相同。

similar question was answered here,但没有说明这种区别。

var o = Object.create(Object.prototype); // same as var o = {};

【问题讨论】:

    标签: javascript


    【解决方案1】:

    您通常希望使用Object.create(prototype) 从另一个对象创建对象,并使用Object.create(Class.protoype) 从函数创建对象。

    执行Object.create(Class) 将使用函数作为模板,这意味着只有“静态”字段将被传输到新对象。 Object.create(Class.protoype) 将使用原型作为模板,因此您将能够获取使用 Class.prototype.field 声明的所有字段,您还可以通过构造函数获取静态字段,最后,一旦在构造函数上运行新对象,在构造函数中声明的字段也将被创建。

    function Foo() {
      // Only visible by prototype after running constructor
      this.test = function() {};
    }
    Foo.prototype.bar = "Bar"; // Visible by prototype
    Foo.fooBar = "FooBar"; // Visible by class
    
    var classFoo = Object.create(Foo);
    var protoFoo = Object.create(Foo.prototype);
    
    // fooBar is static, so it can be viewd bu classFoo
    console.log(classFoo.fooBar); 
    // bar was added to the prototype, cant be viewed
    console.log(classFoo.bar); 
    // test is declared in the constructor, to which there is no pointer from classFoo
    console.log(classFoo.test); 
    // this constructor is the base constructor for all classes
    console.log(classFoo.constructor); 
    
    // fooBar was added to the constructor, so it cannot be viewed this way
    console.log(protoFoo.fooBar); 
    // but it can be viewed like this
    console.log(protoFoo.constructor.fooBar); 
    // this is the Foo function/constructor
    console.log(protoFoo.constructor); 
    // bar is added to the prototype so it can be viewed
    console.log(protoFoo.bar); 
    // test has not been declared yet as the constructor has not been run yet
    console.log(protoFoo.test);
    // the foo function is run with protoFoo as this
    protoFoo.constructor();
    // the test function has now been added to protoFoo
    console.log(protoFoo.test);

    【讨论】:

      【解决方案2】:

      Child.prototype = Object.create(Parent.prototype)Child.prototype = Object.create(Parent) 相比将形成不同的原型链

      Child.prototype = Object.create(Parent.prototype)

      foo 的原型链是 Child.prototype ---> Parent.prototype ----> Object.prototype

      简单说明

      • foo是从Child创建的,所以它的原型是Child.prototype
      • Child.prototype 是从 Object.create(Parent.prototype) 创建的,所以它的原型是 Parent.prototype。
      • Parent.prototype 是从 Object 创建的,所以它的原型是 Object.prototye
      • Object.prototype 的原型为空。这就是链条的终点。

      Child.prototype = Object.create(Parent);

      foo 的原型链会有所不同,如下所示 Child.prototype ---> Parent ----> Function.prototype ----> Object.prototype

      简单说明

      • foo是从Child创建的,所以它的原型是Child.prototype
      • Child.prototype 是从 Object.create(Parent) 创建的,所以它的原型是 Parent
      • Parent是从Function创建的,所以它的原型是Function.prototype
      • Function.prototype是从Object创建的,所以它的原型是Object.prototype
      • 如果 Object.prototype 为空,则为原型。这就是链条的终点。

      您可以通过调用进一步验证每种情况下的原型链。名称在 Function.prototype 中定义。

      console.log(foo.name);
      

      对于第一种情况,你会得到 undefined 因为 Function.prototype 不在原型链中,而在第二种情况下,你会得到“Parent”作为 console.log 的输出

      【讨论】:

        猜你喜欢
        • 2011-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多