JavaScript中的`new`做什么呢?

我很困惑如何构造函数在Javascrpt中工作; 尽pipe使用了几年的语言(大部分就像是LISP的半必要版本),但我想更多地了解对象应该如何工作。

鉴于此代码:

function Foo(x) { return { bar: function() { return x; } }; } 

调用myFoo = Foo(5)myFoo = new Foo(5)什么myFoo = new Foo(5) ? 或者换句话说,Javascript中的构造函数究竟做了什么

调用myFoo = Foo(5)myFoo = new Foo(5)什么myFoo = new Foo(5)

这段代码没有区别,因为它返回一个对象, 规范说:

  • 结果为调用F的[[Call]]内部属性的结果,提供obj作为this值,并将传递给[[Construct]]的参数列表提供为args。
  • 如果Type(result)Object则返回结果

由于该函数返回的是Object的结果,因此使用它的结果。 如果它没有返回一个对象,或者如果它检查了this ,你会注意到一个区别,例如,如果你把它改写为:

 function Foo(x) { if (!(this instanceof Foo)) { return new Foo(x); } this.bar = function() { return x; }; } // Now instanceof works. alert((new Foo) instanceof Foo); 

无论如何,JavaScript中有什么new呢?

new运算符使该函数被绑定到一个新创build的Object ,该Object的原型是该函数的prototype属性。

对于用户定义的function,

 new f(a, b, c) 

相当于

 // Create a new instance using f's prototype. var newInstance = Object.create(f.prototype), result; // Call the function result = f.call(newInstance, a, b, c), // If the result is a non-null object, use it, otherwise use the new instance. result && typeof result === 'object' ? result : newInstance 

注意,语言规范实际上用两个操作[[Call]][[Construct]]来定义函数,所以有一些new行为奇怪的情况。

例如,绑定和内置函数:

 var g = f.call.bind(f); 

应该定义一个被调用的函数,就是调用f ,所以g应该和f在所有方面一样,但是

 new g() 

产生

 TypeError: function call() { [native code] } is not a constructor 

因为内build函数Function.prototype.call支持[[Call]]而不支持[[Construct]]

Function.prototype.bind new和常规的调用, Function.prototype.bind也有不同的performance。 this值在被调用的时候总是绑定thisValue,但是在你使用new时候是一个新构造的实例。

在这个例子中,最终结果没有任何区别。

这是因为你的Foo函数正在返回一个对象实例

只有当函数返回一个原始值 (或者它不返回任何东西,这在技术上是undefined值) 时, new运算符才会返回从构造函数的原型inheritance的新创build的对象。

例如:

 function Foo () { return 5; // or "", or null, or no return statement at all (undefined) } var foo = new Foo(); typeof foo; // "object" foo instanceof Foo; // true Foo.prototype.isPrototypeOf(foo); // true 

当你返回一个对象时,从构造函数的原型inheritance的新创build的对象将被丢弃:

 function Foo () { return {}; } var foo = new Foo(); typeof foo; // "object" foo instanceof Foo; // false Foo.prototype.isPrototypeOf(foo); // false 

也可以看看:

  • 构造函数可以返回什么值来避免返回?
  • JavaScript:“新”如何在内部工作

在这个例子中,当你返回一个新的对象的时候,没有什么区别。 它可以被重写为:

 function Foo(x){ this._x = x; } Foo.prototype.bar = function() { return this._x; } 

有了这个语法,每次你调用new Foo ,它将创build一个_x属性的新对象。 好处是bar函数将被存储一次,并被重用于Foo的多个实例。 在多次调用Foo()的问题中,代码将为每个实例创build一个bar函数。 因此,将function附加到原型上而不是直接放在对象上会使内存更轻。

在MDC上可以find原型如何工作的全面细分。