尽管函数包装,但值未在循环中关闭
Value not closed over in a loop, despite function-wrapping
我有一个要循环的对象列表;这些对象中的每一个都有一个 属性 ,它是一个引用 this
的函数。如果我根据我的对象创建一个回调列表,似乎我必须 "double-wrap" 依赖 this
的函数才能维护正确的引用。我不明白这是为什么 - 谁能解释一下?
function Pokemon(name) {
this.name = name;
this.sayName = function() {
console.log(this.name);
};
}
function runFunctions(arrayOfFunctions) {
for (var i = 0, fn; fn = arrayOfFunctions[i]; i++) {
fn();
}
}
var monsters = [
new Pokemon('Charmander'),
new Pokemon('Squirtle'),
new Pokemon('Bulbasaur')
];
var unclosedCalls = [];
var closedCalls = [];
for (var i = 0, monster; monster = monsters[i]; i++) {
var unclosedCall = (function(m) {
return m.sayName
})(monster);
var closedCall = (function(m) {
return function() {
m.sayName();
}
})(monster);
unclosedCalls.push(unclosedCall);
closedCalls.push(closedCall);
}
console.log('--start')
runFunctions(unclosedCalls); // doesn't work
console.log('----')
runFunctions(closedCalls); // works
console.log('--end')
closedCalls
是双重回调的列表。
我不明白为什么 m
在每个 unclosedCall
的创建中实际上并没有结束。
这是一个包含我的代码的 jsbin:http://jsbin.com/qivilusuje/1/edit?js,console,output
"unclosed" 调用的问题是您 return (m.sayName
) 的函数引用立即与变量 m
解除关联,函数 属性 已检索到。
函数引用不知道它是从哪个对象检索的,因此当函数最终被调用时它没有 "context" - this
将被设置为全局对象最初具有此功能的对象的 属性:
var obj = {
func : function() { console.log(this) }
}
obj.func() // outputs "obj" because a.b() calls "b" with "this" === "a"
var ref = obj.func;
ref(); // outputs "window"
要修复它,您可以让未关闭的调用执行 return m.sayName.bind(m)
,尽管已经走到这一步,也不需要 IIFE,而且它也可以这样说:
var unclosedCall = monster.sayName.bind(monster);
我有一个要循环的对象列表;这些对象中的每一个都有一个 属性 ,它是一个引用 this
的函数。如果我根据我的对象创建一个回调列表,似乎我必须 "double-wrap" 依赖 this
的函数才能维护正确的引用。我不明白这是为什么 - 谁能解释一下?
function Pokemon(name) {
this.name = name;
this.sayName = function() {
console.log(this.name);
};
}
function runFunctions(arrayOfFunctions) {
for (var i = 0, fn; fn = arrayOfFunctions[i]; i++) {
fn();
}
}
var monsters = [
new Pokemon('Charmander'),
new Pokemon('Squirtle'),
new Pokemon('Bulbasaur')
];
var unclosedCalls = [];
var closedCalls = [];
for (var i = 0, monster; monster = monsters[i]; i++) {
var unclosedCall = (function(m) {
return m.sayName
})(monster);
var closedCall = (function(m) {
return function() {
m.sayName();
}
})(monster);
unclosedCalls.push(unclosedCall);
closedCalls.push(closedCall);
}
console.log('--start')
runFunctions(unclosedCalls); // doesn't work
console.log('----')
runFunctions(closedCalls); // works
console.log('--end')
closedCalls
是双重回调的列表。
我不明白为什么 m
在每个 unclosedCall
的创建中实际上并没有结束。
这是一个包含我的代码的 jsbin:http://jsbin.com/qivilusuje/1/edit?js,console,output
"unclosed" 调用的问题是您 return (m.sayName
) 的函数引用立即与变量 m
解除关联,函数 属性 已检索到。
函数引用不知道它是从哪个对象检索的,因此当函数最终被调用时它没有 "context" - this
将被设置为全局对象最初具有此功能的对象的 属性:
var obj = {
func : function() { console.log(this) }
}
obj.func() // outputs "obj" because a.b() calls "b" with "this" === "a"
var ref = obj.func;
ref(); // outputs "window"
要修复它,您可以让未关闭的调用执行 return m.sayName.bind(m)
,尽管已经走到这一步,也不需要 IIFE,而且它也可以这样说:
var unclosedCall = monster.sayName.bind(monster);