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

时间:2013-01-29 15:45:00

标签: javascript

在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 );

6 个答案:

答案 0 :(得分:3)

它们在您的示例中不相同,因为bob不会从Person.prototype继承(它直接继承自Object.prototype)。

等效版本将是

Person.call(bob = Object.create(Person.prototype), "Bob", 55 );

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

早期的JS版本中没有

Object.create,因此在没有new的情况下无法设置对象继承(您可以在某些浏览器中覆盖对象的internal __proto__ property ,但那是非常不好的做法。)


作为参考,newhttp://es5.github.com/#x11.2.2定义了Object.create的工作原理。 http://es5.github.com/#x13.2.2中描述了{{1}}。

答案 1 :(得分:2)

不,new不是只是语法糖。相反,Person.call可以(并且只能工作)构建新实例,因为JavaScript allows constructors to be called without new in some cases.

答案 2 :(得分:2)

否。

call()只调用一个函数(另请参阅apply()),而new关键字初始化一个原型中的对象。

虽然原型构造函数是一个函数,但它是一个特例。

答案 3 :(得分:2)

不,不是。如果是第一个例子,那么您实际上是在创建一个Person。

bob instanceof Person == true

在另一个例子中......

bob instanceof Person == false

答案 4 :(得分:1)

创建类型实例的目的是分享一些行为,通常是通过原型。

假设您添加了一个函数:

Person.prototype.doSomething = function(){
   ...
}

然后,此功能可用于使用Person作为new实例创建的所有对象,但不能用于使用call创建的对象。

MDN有good introductory document about the use of the prototype

答案 5 :(得分:1)

当您调用new时,您将该函数作为构造函数调用。这告诉JavaScript,创建一个“新的”Person对象,然后使用设置为this的新对象调用该函数。

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

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

所以,不,一个人对另一个人来说并不缺乏。他们是不同的。