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

?

4

6 回答 6

3

它们在您的示例中不等效,因为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.createhttp://es5.github.com/#x15.2.3.5中有描述。

于 2013-01-29T16:06:17.573 回答
2

不,不仅仅是new语法糖。相反,可以(并且仅可以)构造一个新实例,因为JavaScript 允许在某些情况下不调用构造函数。Person.callnew

于 2013-01-29T15:46:54.233 回答
2

不。

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

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

于 2013-01-29T15:47:02.083 回答
2

不,这不对。如果您的第一个示例,您实际上是在创建一个人。

bob instanceof Person == true

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

bob instanceof Person == false
于 2013-01-29T15:48:27.267 回答
1

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

假设您添加了一个功能:

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

然后这个函数将可用于作为Personusing实例创建的所有对象new,但不适用于您创建的对象 using call

MDN 有一个很好的关于原型使用的介绍文档

于 2013-01-29T15:50:13.567 回答
1

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

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

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

所以,不,一个不是另一个的缩写。它们是不同的。

于 2013-01-29T15:51:43.887 回答