JavaScript 中的 `new` 有什么作用呢? [英] What does `new` in JavaScript do, anyway?
问题描述
我对构造函数在 Javascrpt 中的工作方式感到非常困惑;尽管使用该语言已有数年(主要就好像它就像 LISP 的半命令式版本),但我想更多地了解对象应该如何在其中工作.
鉴于此代码:
function Foo(x) {返回 {酒吧:函数(){返回x;}};}
调用 myFoo = Foo(5)
和 myFoo = new Foo(5)
有什么区别?或者,换句话说,Javascript 中的构造函数究竟做了什么do?
调用
myFoo = Foo(5)
和myFoo = new Foo(5)
有什么区别?
该代码没有区别,因为它返回一个对象,并且规范说:
<块引用>- 让 result 是调用 F 的 [[Call]] 内部属性的结果,提供 obj 作为
this
值并提供作为参数传入 [[Construct]] 的参数列表. - 如果
Type(result)
是Object
,则返回 result.
由于该函数返回的结果是一个对象,因此使用其结果.如果它没有返回一个对象,或者如果它检查了this
,你会注意到一个不同,例如如果你把它改写为:
function Foo(x) {if (!(this instanceof Foo)) { return new Foo(x);}this.bar = function() { 返回 x;};}//现在 instanceof 起作用了.alert((new Foo) instanceof Foo);
<块引用>
JavaScript 中的 new
到底做了什么?
new
操作符导致函数被调用,this
绑定到一个新创建的 Object
,其原型是该函数的 prototype
属性.
对于用户定义的函数,
new f(a, b, c)
相当于
//使用 f 的原型创建一个新实例.var newInstance = Object.create(f.prototype), result;//调用函数结果 = f.call(newInstance, a, b, c),//如果结果是非空对象,则使用它,否则使用新实例.结果&&结果类型 === '对象' ?结果:新实例
注意,语言规范实际上定义了两个操作的函数,[[Call]] 和 [[Construct]],所以在某些极端情况下 new
的行为很奇怪.
例如绑定和内置函数:
var g = f.call.bind(f);
应该定义一个函数,调用时只调用f
,所以g
在各方面都应该和f
相同,但是
new g()
生产
TypeError: function call() { [native code] } 不是构造函数
因为内置函数 Function.prototype.call
支持 [[Call]] 但不支持 [[Construct]].
Function.prototype.bind
在 new
和常规调用方面的行为也不同.this
值在调用时始终是绑定的 thisValue,但在使用 new
时是新构造的实例.
I am very confused about how constructors work in Javascrpt; despite using the language for several years (mostly as if it were like a semi-imperative version of LISP) I would like to know more about how objects are supposed to work in it.
Given this code:
function Foo(x) {
return {
bar: function() { return x; }
};
}
What is the difference between calling myFoo = Foo(5)
and myFoo = new Foo(5)
? Or, in other words, what exactly does a constructor in Javascript do?
What is the difference between calling
myFoo = Foo(5)
andmyFoo = new Foo(5)
?
There's no difference for that code, because it returns an object, and the spec says:
- Let result be the result of calling the [[Call]] internal property of F, providing obj as the
this
value and providing the argument list passed into [[Construct]] as args.- If
Type(result)
isObject
then return result.
Since that function returns a result that is an Object, its result is used. You would notice a difference if it did not return an object, or if it checked this
, for example if you rewrote it as:
function Foo(x) {
if (!(this instanceof Foo)) { return new Foo(x); }
this.bar = function() { return x; };
}
// Now instanceof works.
alert((new Foo) instanceof Foo);
What does
new
in JavaScript do, anyway?
The new
operator causes the function to be called with this
bound to a newly created Object
whose prototype is that function's prototype
property.
For user-defined functions,
new f(a, b, c)
is equivalent to
// 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
Note, that the language specification actually defines functions with two operations, [[Call]] and [[Construct]], so there are some corner cases where new
behaves oddly.
For example, bound and built-in functions:
var g = f.call.bind(f);
should define a function that when called, just calls f
, so g
should be the same as f
in all respects, but
new g()
produces
TypeError: function call() { [native code] } is not a constructor
because the builtin function Function.prototype.call
supports [[Call]] but not [[Construct]].
Function.prototype.bind
also behaves differently around new
and regular calls. The this
value is always the bound thisValue when called, but is a newly constructed instance when you use new
.
这篇关于JavaScript 中的 `new` 有什么作用呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!