JavaScript 中的 `new` 只是 `.call` 的语法糖吗?

7
在JavaScript中,我想知道new是否有什么特殊之处,或者它只是call()的语法糖。如果我有一个构造函数如下:
function Person ( name, age ){
    this.name = name;
    this.age = age;
}


var bob = new Person( "Bob", 55 );

与任何不同
var bob;
Person.call( bob = new Object(), "Bob", 55 );

?


2
它们并不等价,等价版本应该是 Person.call( bob = Object.create(Person.prototype), "Bob", 55 );。这是语法糖吗?这可能取决于你如何定义它。在早期的JS版本中,Object.create是不可用的。 - Felix Kling
@FelixKling 可能应该把它作为答案而不是评论,这是一个好建议。 :) - Sled
6个回答

4
在你的例子中,它们并不等价,因为bob没有继承自Person.prototype(而是直接继承自Object.prototype)。
等价的版本应该是:
Person.call(bob = Object.create(Person.prototype), "Bob", 55 );

这算是语法糖吗?可能取决于您如何定义它。

Object.create在早期的JS版本中不可用,因此没有办法设置对象继承而不使用new(您可以在某些浏览器中覆盖对象的内部__proto__属性,但这是非常糟糕的实践)。


作为参考,new的工作原理在http://es5.github.com/#x11.2.2http://es5.github.com/#x13.2.2中有定义。 Object.create的说明在http://es5.github.com/#x15.2.3.5中描述。


2
不,不是这样的。在你的第一个例子中,你实际上正在创建一个人员(Person)。
bob instanceof Person == true

在另一个例子中...

bob instanceof Person == false

2

2

编号.

call()仅调用一个函数(另请参见apply()),而new关键字则从原型初始化一个对象。

虽然原型构造函数确实是一个函数,但它是一个特殊情况。


1
创建一个类型实例的目的是通过原型共享一些行为。
假设你添加了一个函数:
Person.prototype.doSomething = function(){
   ...
}

那么,此函数将对使用new创建的所有Person实例对象可用,但不适用于使用call创建的对象。
MDN有一篇关于原型使用的良好介绍文档

1
当你调用new时,你正在将函数作为构造函数来调用。这告诉JavaScript制作一个"新的"Person对象,然后使用该新对象作为this调用函数。

在第二个示例中,您正常调用函数,并手动将this设置为new Object(或只是{})。因此,函数运行并设置您发送给它的this对象的属性。(尝试只执行Person("Bob", 55);,然后console.log(window.name))

在第一个示例中,bob是一个Person对象;但在第二个示例中,它是一个Object

所以,不,一个不是另一个的简称。他们是不同的。


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