为什么Object.create()和new Object()会产生不同的原型?

21

为什么这两个实现行为不同? 当评估它们的原型时,究竟是什么使它们不同?

使用指定的原型创建对象:

   function Foo() {}

   // creates an object with a specified prototype
   var bar = Object.create(Foo);

   console.log(Object.getPrototypeOf(bar)); // returns: function Foo(){}
   console.log(Foo.isPrototypeOf(bar)); // returns: true

使用构造函数创建对象:

   function Foo() {}

   // creates an object with the constructor method    
   var bar = new Foo();

   console.log(Object.getPrototypeOf(bar)); // returns: Foo {}
   console.log(Foo.isPrototypeOf(bar)); // returns: false

另外,为什么第二个实现会返回Foo {}false


1
“此外,第二个实现为什么会同时返回 Foo {} 和 false?”是一个很好的问题。我已经更新了我的答案来解决这个问题。 - joews
3
请注意,通常您会执行var bar = Object.create( Foo.prototype );,这样可以得到期望的行为。 - Paul
2个回答

22

Object.create(Foo) 的意思是“创建一个以 Foo 为原型的对象”。

new Foo() 的意思是“创建一个以 Foo.prototype 为原型、以 Foo 为构造函数的对象”。

因此,在第一个例子中,FooBar 的原型,在第二个例子中,FooBar 的构造函数。

我认为你问题的第二部分是由误导性的控制台输出引起的 - Object.getPrototypeOf(bar) 实际上返回的是 Foo.prototype,而不是 Foo

function Foo() {}
var bar = new Foo();

Object.getPrototypeOf(bar) === Foo
// -> false

Object.getPrototypeOf(bar) === Foo.prototype
// -> true

11

当你使用“new”关键字来实例化一个对象时,JavaScript实际上会为你的对象添加两行代码。

如果你想用伪类实例化来创建一个对象,你可以像这样创建:

var Foo = function() {
this.property = 'baz';
};

当你调用var bar = new Foo()时,Javascript会将Foo运行为以下内容:

var Foo = function() {
// ADDED CODE: var this = Object.create(Foo.prototype);
this.property = 'baz';
// ADDED CODE: return this;

使用 Object.create 创建一个代理关系,新创建的对象会将其查找委托给指定的对象。因此,在第一个例子中,bar 委托其查找给 Foo,但在第二个例子中,查找被委托给了 Foo.prototype。

您可能会发现这篇博客文章很有趣。其中讨论了伪经典实例化(使用 new 关键字)和原型实例化之间的区别,后者不使用 new 关键字。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接