编辑:我要道歉,我发布的问题实际上并不存在于我发布的代码中,因为我过分简化了它。我稍后会尝试发布一些内容。
删除也没关系,但目前答案太多,所以我不能自己做。
编辑2:好的,这里是:
让,
function F() {
this.field = "value" ;
var init = function(value) {
this.field = value ;
} ;
this.method = function() {
return this.field ;
} ;
init( arguments[0] ) ;
}
现在,实例化F
类型,
var f = new F("newValue") ;
会将值设置为Window
对象,因为this
在从闭包调用时指向它。
将this
绑定到Function
,
function F() {
var self = this ;
this.field = "value" ;
var init = function(value) {
self.field = value ;
} ;
this.method = function() {
return this.field ;
} ;
init( arguments[0] ) ;
}
将解决问题。
仍然,这是什么原因 - 这种奇怪的行为?
答案 0 :(得分:2)
这是(引用)调用函数的对象。
因此,在f.method()
来电中,this
为“f”。不是“F”。
var self = this;
有效的事实不是由于此声明本身,而是由于method2()
是 closure
更具体地说,self
中的变量method2()
的范围由F()
确定 - 换句话说,method2()
中的“自我”将始终引用当定义“F”时存在的self
的值(当时,当然是“F”,因为此时当前对象上下文是“F”)。
答案 1 :(得分:1)
将this
称为“运营商”是不正确的。它是运行时在函数激活时建立的对象引用。
Javascript只是一种以不同方式处理事物的不同语言。 this
受到程序员的控制非常强大。
此外,除非您发布的其他内容为“F”设置原型对象,否则该代码肯定不起作用。 “method”和“method2”都不能从对“F”实例的引用中调用。
答案 2 :(得分:1)
对于方法的定义,您可能希望执行更类似的操作:
this.method = function()
{
return this.field;
}
答案 3 :(得分:1)
这是你要找的例子吗?
var F = function() {
var self = this ; //!! points correctly to the Function Object
this.field = "someValue" ;
var helper1 = function(){
return self.field;
}
var helper2 = function(){
return this.field;
}
this.method = function(){
return helper1();
}
this.method2 = function(){
return helper2();
}
}
var f = new F() ;
console.log(f.method()) ;
console.log(f.method2()) ;
在方法的情况下,它调用使用self的helper,它在创建时指向f,因此它可以工作。
在method2的情况下,它使用helper2,它使用它。但是在helper2内部的含义是'全局'范围,因此返回undefined。
答案 4 :(得分:1)
事实证明,这是ECMAScript(因此JavaScript)的ECMA规范的一个黑暗角落:
最后,为this关键字指定一个值。如果赋值已引用对象,则属性访问器以该对象的this关键字引用属性为前缀。如果分配的值(内部)为null,则this关键字将引用全局对象。
(http://jibbering.com/faq/notes/closures/;感谢@ Brian Flanagan的链接)
显然,在执行分配给变量的函数(在另一个Function
内)时,上下文丢失,因此范围设置为null,this
将引用{{1 }} Window
。
我不太确定这是否可以从Object
初始化为局部变量。通常情况下,我希望闭包能够访问它在内存中创建的范围,包括它在范围链中的前身。
此行为与Function
Function
的属性的函数不同,其中上下文不会丢失,Object
将正确指向成员this
的所有者(Function
Function
或成员,具体取决于有多少层。
此问题的解决方案(同时维护私有Object
成员,即只能从Function
范围内访问的成员)使用{将函数包装在另一个Function
内{1}}(或Function
)手动设置上下文:
Function.prototype.apply
这类似于JavaScript 1.85以及PrototypeJS库中引入的Function.prototype.call
。
编辑:function F() {
this.field = "value" ;
var self = this ;
var init = function(value) {
(function() {
this.field = value ;
}).apply(self,value) ;
} ;
this.method = function() {
return this.field ;
} ;
init( arguments[0] ) ;
}
中所附功能周围的圆括号。这将产生Function.prototype.bind
。