首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么这个指令中的所有键绑定都会被最后一个键绑定覆盖?

为什么这个指令中的所有键绑定都会被最后一个键绑定覆盖?
EN

Stack Overflow用户
提问于 2013-01-15 11:05:22
回答 1查看 736关注 0票数 0

我试图创建一个指令,将特定的按键绑定到控制器作用域中指定的函数,但所有回调函数似乎都被包含绑定的对象中的最后一个回调函数覆盖。我已经尝试使用keymaster.js和mousetrap.js来绑定具有相同结果的事件。

Code in a JSFiddle

Javascript代码:

代码语言:javascript
运行
复制
angular.module('app', ['directives', 'controllers']);

angular.module('directives', [])
.directive('keypress', [function () {
    return function (scope, element, attrs) {
        // console.log(scope, element, attrs);
        var attribute = scope.$eval(attrs.keypress || '{}');
        for (var k in attribute) {
            console.log('binding ' + k + ' as ' + attribute[k]);
            Mousetrap.bind(k, function() { return attribute[k](scope, element); });
        }
    };
}]);

angular.module('controllers', [])
.controller('TodoController', function($scope) {
    $scope.shortcuts = {
        'w': function () { console.log('w'); },
        's': function () { console.log('s'); },
        'a': function () { console.log('a'); },
        'd': function () { console.log('d'); }
    };
});

HTML文件:

代码语言:javascript
运行
复制
<html>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.js"></script>
    <script src="https://raw.github.com/ccampbell/mousetrap/master/mousetrap.min.js"></script>
    <script src="/javascript/app.js"></script>
  </head>
  <body>
    <div ng-app="app">
      <div ng-controller='TodoController' keypress='shortcuts'>Foo</div>
    </div>
  </body>
</html>

为什么无论我按下'w‘、'a’、's‘还是'd’,'d‘总是写入控制台?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-15 11:14:47

您落入了一个常见的陷阱: JavaScript中的变量始终是函数作用域。执行此操作时:

代码语言:javascript
运行
复制
for (var k in attribute) {
    console.log('binding ' + k + ' as ' + attribute[k]);
    Mousetrap.bind(k, function() { return attribute[k](scope, element); });
}

有了这个bind(),您将创建四个闭包,它们都关闭在变量k-but上,它们都关闭在同一个变量上。您不会在每次循环运行时都获得一个新的。因为k的值是立即使用的,所以console.log可以很好地工作。在实际运行之前,闭包不会对k求值,到那时,它的值已经更改为循环结束时的值。

根据您的目标受众,到目前为止解决此问题的最简单方法是使用let而不是varlet确实做了块作用域(它的工作方式与您期望的差不多),但它是一个相当新的发明,我不确定它得到了多好的支持。

否则,要获得一个新的作用域,您需要一个新函数:

代码语言:javascript
运行
复制
for (var k in attribute) {
    (function(k) {
        console.log('binding ' + k + ' as ' + attribute[k]);
        Mousetrap.bind(k, function() { return attribute[k](scope, element); });
    })(k);
}

这会将外部k传递给函数的内部k,它每次都是一个不同的变量。你也可以把它拆分成一个小的工厂函数,但是对于这么小的东西,我不会费心的。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14330527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档