关于构造函数在Javascrpt中的工作原理,我感到非常困惑.尽管使用该语言已有好几年了(大多数情况下它就像是LISP的半命令版本),但我想更多地了解对象应该如何工作.
鉴于此代码:
function Foo(x) {
return {
bar: function() { return x; }
};
}
Run Code Online (Sandbox Code Playgroud)
打电话myFoo = Foo(5)和有myFoo = new Foo(5)什么区别?或者,换句话说,Javascript中的构造函数究竟是做什么的?
Mik*_*uel 49
打电话
myFoo = Foo(5)和有myFoo = new Foo(5)什么区别?
该代码没有区别,因为它返回一个对象,规范说:
- 设result是调用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);
Run Code Online (Sandbox Code Playgroud)
是什么
new在JavaScript做啊?
该new操作将导致函数来调用this绑定到新创建的Object,其原型是函数的prototype性质.
对于用户定义的功能,
new f(a, b, c)
Run Code Online (Sandbox Code Playgroud)
相当于
// 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
Run Code Online (Sandbox Code Playgroud)
注意,语言规范实际上定义了具有两个操作的函数,[[Call]]和[[Construct]],因此存在一些new奇怪的行为.
例如,绑定和内置函数:
var g = f.call.bind(f);
Run Code Online (Sandbox Code Playgroud)
应该定义一个函数,在调用时,只调用f,所以g应该f在所有方面都相同,但是
new g()
Run Code Online (Sandbox Code Playgroud)
产生
TypeError: function call() { [native code] } is not a constructor
Run Code Online (Sandbox Code Playgroud)
因为内置函数Function.prototype.call支持[[Call]]而不支持[[Construct]].
Function.prototype.bind周围new和常规电话也表现不同.this调用时,该值始终是绑定的thisValue,但在使用时是一个新构造的实例new.
CMS*_*CMS 13
在这个特定的例子中,最终结果没有区别.
这是因为您的Foo函数正在返回一个对象实例.
该new运算符返回一个新创建的对象,从构造函数的原型继承,只有当函数返回原始值(或它不返回任何东西,这是技术上的undefined值).
例如:
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
Run Code Online (Sandbox Code Playgroud)
返回对象时,从构造函数原型继承的新创建的对象将被丢弃:
function Foo () {
return {};
}
var foo = new Foo();
typeof foo; // "object"
foo instanceof Foo; // false
Foo.prototype.isPrototypeOf(foo); // false
Run Code Online (Sandbox Code Playgroud)
也可以看看:
在这种情况下,当您返回一个新对象时没有区别.它可以改写为:
function Foo(x){
this._x = x;
}
Foo.prototype.bar = function() {
return this._x;
}
Run Code Online (Sandbox Code Playgroud)
每次调用new Foo它时都会使用此语法创建一个属性为的新对象_x.好处是该bar函数将被存储一次并重用于Foo的多个实例.使用Foo()多次调用的问题中的代码将为每个实例创建一个条形函数.因此,将函数附加到原型而不是将它们直接放在对象上会使内存更轻松.
可以在MDC上找到原型工作方式的完整细分.
| 归档时间: |
|
| 查看次数: |
8288 次 |
| 最近记录: |