我最近偶然发现了JavaScript中的object .create()方法,并试图推断它与使用new SomeFunction()创建对象的新实例有何不同,以及当您想要使用其中一个而不是另一个时。

考虑下面的例子:

var test = { val: 1, func: function() { return this.val; } }; var testA = Object.create(test); testA.val = 2; console.log(test.func()); // 1 console.log(testA.func()); // 2 console.log('other test'); var otherTest = function() { this.val = 1; this.func = function() { return this.val; }; }; var otherTestA = new otherTest(); var otherTestB = new otherTest(); otherTestB.val = 2; console.log(otherTestA.val); // 1 console.log(otherTestB.val); // 2 console.log(otherTestA.func()); // 1 console.log(otherTestB.func()); // 2

请注意,在这两种情况下观察到相同的行为。在我看来,这两种情况的主要区别是:

在object .create()中使用的对象实际上形成了新对象的原型,而在new Function()中声明的属性/函数不形成原型。 不能像使用函数式语法一样使用Object.create()语法创建闭包。考虑到JavaScript的词法(相对于块)类型范围,这是合乎逻辑的。

上述说法正确吗?我是不是遗漏了什么?什么时候你会使用其中一种而不是另一种?

编辑:链接到上述代码示例的jsfiddle版本:http://jsfiddle.net/rZfYL/


当前回答

内部对象。Create是这样做的:

Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
};

语法只是消除了JavaScript使用经典继承的错觉。

其他回答

区别在于所谓的“伪经典vs.原型继承”。建议在代码中只使用一种类型,不要混合使用两种类型。

在伪经典继承中(使用"new"操作符),假设您首先定义了一个伪类,然后从该类创建对象。例如,定义一个伪类“Person”,然后从“Person”创建“Alice”和“Bob”。

在原型继承中(使用Object.create),您直接创建一个特定的人“Alice”,然后使用“Alice”作为原型创建另一个人“Bob”。这里没有“阶级”;都是对象。

在内部,JavaScript使用“原型继承”;“伪古典”的方式只是一些糖。

查看这两种方法的比较。

内部对象。Create是这样做的:

Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
};

语法只是消除了JavaScript使用经典继承的错觉。

这样的:

var foo = new Foo();

and

var foo = Object.create(Foo.prototype);

非常相似。一个重要的区别是,new Foo实际上运行构造函数代码,而Object。创建将不会执行诸如

function Foo() {
    alert("This constructor does not run with Object.create");
}

请注意,如果使用Object.create()的双参数版本,则可以执行更强大的操作。

function Test(){
    this.prop1 = 'prop1';
    this.prop2 = 'prop2';
    this.func1 = function(){
        return this.prop1 + this.prop2;
    }
};

Test.prototype.protoProp1 = 'protoProp1';
Test.prototype.protoProp2 = 'protoProp2';
var newKeywordTest = new Test();
var objectCreateTest = Object.create(Test.prototype);

/* Object.create   */
console.log(objectCreateTest.prop1); // undefined
console.log(objectCreateTest.protoProp1); // protoProp1 
console.log(objectCreateTest.__proto__.protoProp1); // protoProp1

/* new    */
console.log(newKeywordTest.prop1); // prop1
console.log(newKeywordTest.__proto__.protoProp1); // protoProp1

简介:

1)用new关键字有两点要注意;

A)函数被用作构造函数

b)函数。原型对象被传递给__proto__属性…或者在不支持__proto__的地方,它是新对象寻找属性的第二个地方

2)使用object .create(obj.prototype)你正在构造一个对象(obj.prototype)并将其传递给预期的对象。不同的是,现在new object的__proto__也指向obj。原型(请参考ans by xj9)

Object.create(Constructor.prototype)是new Constructor的一部分

这是新的构造函数实现

// 1. define constructor function

      function myConstructor(name, age) {
        this.name = name;
        this.age = age;
      }
      myConstructor.prototype.greet = function(){
        console.log(this.name, this.age)
      };

// 2. new operator implementation

      let newOperatorWithConstructor = function(name, age) {
        const newInstance = new Object(); // empty object
        Object.setPrototypeOf(newInstance, myConstructor.prototype); // set prototype

        const bindedConstructor = myConstructor.bind(newInstance); // this binding
        bindedConstructor(name, age); // execute binded constructor function

        return newInstance; // return instance
      };

// 3. produce new instance

      const instance = new myConstructor("jun", 28);
      const instance2 = newOperatorWithConstructor("jun", 28);
      console.log(instance);
      console.log(instance2);
      

new构造函数实现包含Object。创建方法

      newOperatorWithConstructor = function(name, age) {
        const newInstance = Object.create(myConstructor.prototype); // empty object, prototype chaining

        const bindedConstructor = myConstructor.bind(newInstance); // this binding
        bindedConstructor(name, age); // execute binded constructor function

        return newInstance; // return instance
      };

      console.log(newOperatorWithConstructor("jun", 28));