问题与Coffeescript的理解和关闭 [英] Issue with Coffeescript comprehensions and closures
问题描述
将一些JavaScript转换为CoffeeScript时遇到问题。基本问题是我从使用$ .each到CoffeeScript的理解,我现在有一个问题,在理解的最后一个值被捕获在closures。让我们从原始的JavaScript开始:
function bindKeyboardControls(websocket){
var moveKeyMap = {
Down :['down','s'],
Up:['up','w'],
Left:['left','a'],
Right: 'right','d']
};
$ .each(moveKeyMap,function(direction,keys){
$ .each(keys,function(_,key){
$(document).bind keydown',key,function(){move(websocket,direction);});
});
});
};
这是我第一次尝试CoffeeScript:
bindKeyboardControls =(websocket) - >
moveKeyMap =
Down:['down','s']
Up:['up','w']
Left:['left','a' ]
Right:['right','d']
for direction,keys of moveKeyMap
for key in keys
$(document).bind('keydown',key , - > move(websocket,direction))
null
工作?这里是生成的JavaScript:
bindKeyboardControls = function(websocket){
var direction,key,keys,moveKeyMap, _i,_len;
moveKeyMap = {
Down:['down','s'],
Up:['up','w'],
Left:['left' 'a'],
Right:['right','d']
};
for(在moveKeyMap中的方向){
keys = moveKeyMap [direction];
for(_i = 0,_len = keys.length; _i< _len; _i ++){
key = keys [_i];
$(document).bind('keydown',key,function(){
return move(websocket,direction);
});
}
}
return null;
};
你看到'direction'变量是如何在函数的顶部声明的吗?传递给document.bind的函数是在该变量上创建一个闭包,所以在函数运行时,direction将总是等于最后一个值('Right')。
这是一个固定的版本,有点丑陋:
bindKeyboardControls =(websocket) - >
我也可以回到使用$ .each。所以我有一些解决方案,但有更好的解决方案吗?
moveKeyMap =
Down:['down','s']
Up:['up','w']
Left:['left','a' ]
Right:['right','d']
for direction,keys of moveKeyMap
for key in keys
((d) - > $(document)。 bind('keydown',key, - > move(websocket,d)))(direction)
null
解决方案是:
用于方向,moveKeyMap的键
用于键入键
do(direction,key) - > $(document).bind('keydown',key, - > move(websocket,d))
创建并运行一个匿名函数,捕获
direction
和键
的值,以使bind
回调可以使用它们。有关详情,请参阅我的PragProg文章 CoffeeScript Intervention 。I ran into a problem when converting some JavaScript to CoffeeScript. The basic issue is I went from using $.each to CoffeeScript comprehensions and I now have a problem where the last value of the comprehension is being captured in closures. Lets start with the original JavaScript:
function bindKeyboardControls(websocket) { var moveKeyMap = { Down: ['down', 's'], Up: ['up', 'w'], Left: ['left', 'a'], Right: ['right', 'd'] }; $.each(moveKeyMap, function (direction, keys) { $.each(keys, function (_, key) { $(document).bind('keydown', key, function () { move(websocket, direction); }); }); }); };
Here is my first attempt with CoffeeScript:
bindKeyboardControls = (websocket) -> moveKeyMap = Down: ['down', 's'] Up: ['up', 'w'] Left: ['left', 'a'] Right: ['right', 'd'] for direction, keys of moveKeyMap for key in keys $(document).bind('keydown', key, -> move(websocket, direction)) null
Why doesn't this work? Well here's the generated JavaScript:
bindKeyboardControls = function(websocket) { var direction, key, keys, moveKeyMap, _i, _len; moveKeyMap = { Down: ['down', 's'], Up: ['up', 'w'], Left: ['left', 'a'], Right: ['right', 'd'] }; for (direction in moveKeyMap) { keys = moveKeyMap[direction]; for (_i = 0, _len = keys.length; _i < _len; _i++) { key = keys[_i]; $(document).bind('keydown', key, function() { return move(websocket, direction); }); } } return null; };
Do you see how the 'direction' variable is declared at the top of the function? The function that is being passed in to document.bind is creating a closure on that variable, so by the time the function runs, direction will always be equal to the last value ('Right').
Here is a fixed version that is somewhat ugly:
bindKeyboardControls = (websocket) -> moveKeyMap = Down: ['down', 's'] Up: ['up', 'w'] Left: ['left', 'a'] Right: ['right', 'd'] for direction, keys of moveKeyMap for key in keys ((d) -> $(document).bind('keydown', key, -> move(websocket, d)))(direction) null
I could also just go back to using $.each. So I do have some solutions, but is there a better one?
解决方案Yes:
for direction, keys of moveKeyMap for key in keys do (direction, key) -> $(document).bind('keydown', key, -> move(websocket, d))
That creates and runs an anonymous function that captures the values of
direction
andkey
, so that the thebind
callback can use them. See my PragProg article A CoffeeScript Intervention for more on this.这篇关于问题与Coffeescript的理解和关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!