我最近偶然发现了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/


当前回答

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

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

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

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

查看这两种方法的比较。

其他回答

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

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

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

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

查看这两种方法的比较。

简单地说,new X是Object.create(X.prototype),另外运行构造函数。(并让构造函数有机会返回实际的对象,该对象应该是表达式的结果,而不是这个。)

就是这样。:)

剩下的答案令人困惑,因为显然也没有人会读new的定义。;)

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

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

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

object中使用的对象。create实际上形成了新对象的原型,而在new Function()形式中,声明的属性/函数不形成原型。

是的,对象。Create构建一个直接继承作为其第一个参数传递的对象的对象。

使用构造函数,新创建的对象继承自构造函数的原型,例如:

var o = new SomeConstructor();

在上面的例子中,o直接继承自SomeConstructor.prototype。

这里有一个不同,对象。你可以创建一个不继承任何东西的对象object .create(null);,另一方面,如果你设置SomeConstructor。原型= null;新创建的对象将继承object .prototype。

你不能用对象创建闭包。像使用函数式语法一样创建语法。考虑到JavaScript的词法(相对于块)类型范围,这是合乎逻辑的。

你可以创建闭包,例如使用属性描述符参数:

var o = Object.create({inherited: 1}, {
  foo: {
    get: (function () { // a closure
      var closured = 'foo';
      return function () {
        return closured+'bar';
      };
    })()
  }
});

o.foo; // "foobar"

注意,我说的是ECMAScript第5版对象。create方法,而不是Crockford's shim。

该方法已开始在最新的浏览器上本机实现,请检查此兼容性表。

下面是两个调用内部发生的步骤: (提示:唯一的区别是在步骤3)


新的测试():

创建新的Object() obj obj。__proto__ to Test.prototype return Test.call(obj) || obj; //通常返回obj,但JS中的构造函数可以返回一个值


对象。创建(测试。原型)

创建新的Object() obj obj。__proto__ to Test.prototype 返回obj;


基本上就是Object。Create不执行构造函数。