没有为构造器原型方法使用`new`关键字变异原始对象

时间:2018-12-04 19:33:47

标签: javascript

给出以下代码,我将记录Person原型的2个实例

function Person(name) {
  this.name = name
}

person = new Person('bob');
person2 = new person.constructor('tom')
console.log(person);
console.log(person2);

有趣的是,如果我们像下面的示例一样省略new关键字:

function Person(name) {
  this.name = name
}

person = new Person('bob');
person2 = person.constructor('tom')
console.log(person);
console.log(person2);

实际上似乎重新构造了构造函数,并使用新参数对对象进行了变异。这是怎么回事吗?

如果没有new关键字,则什么也不会返回到person2。并且person的名称属性现在为'tom'

如果before为true,则不带new关键字的构造函数会使原始对象发生突变,是否存在用例需要再次在对象上调用构造函数的情况?

3 个答案:

答案 0 :(得分:3)

如果在没有new关键字的情况下调用ES5构造函数(即,调用了 而不是 constructed ),则它没有{{1 }}语句,它将返回return

此外,您正在通过this undefined调用person作为函数调用的dot notation上下文的构造函数,这等效于{{3} },因此它将覆盖您初始化的第一个实例的名称。


当ES5是最新规范时,一种相关的模式在某种程度上曾经很常见,那就是通过使用person.constructor.call(person, 'tom')检查来避免滥用该构造函数,从而使用自校正构造函数。在这种情况下不会被捕获,但是如果您调用person.constructor('tom')而不是Person('tom')会被捕获,这会更常见:

new Person('tom')

答案 1 :(得分:2)

当您不使用new时,Person只是一个常规函数。调用它将接受一个参数,并在name上设置this属性。以这种方式调用this是指您刚刚创建的实例。该函数不返回任何内容,因此本质上是一个setter。

您偶尔会在继承模式中看到这种对构造函数的使用:

function SuperClass(name) {
  this.name = name
}

function ChildClass(city, name) {
  this.city = city
  // use the superClass constructor to set properties:
  SuperClass.call(this, name)
}
// manipulate prototype 

let me = new ChildClass("Anchorage", "Mark")
console.log(me)

在其他情况下利用此功能可能会使您不必要地混淆,因为您只能创建专用的setter函数。

答案 2 :(得分:1)

来自MDN的有关new运算符的信息:

  

new运算符创建用户定义对象类型的实例,或者   具有构造函数的内置对象类型之一   函数。new关键字执行以下4件事

     
      
  1. 它凭空创造了一个全新的物体。
  2.   
  3. 它将这个对象链接到另一个对象
  4.   
  5. 步骤1中新创建的对象作为此上下文传递
  6.   
  7. 如果函数未返回其自身的对象,则返回该
  8.   

如果在不使用new运算符的情况下调用构造函数,则该构造函数的操作就像其他Object方法一样。