JavaScript `bind` 方法没有按预期工作

JavaScript `bind` method does not work as expected

以下控制器工作正常。

 app.controller('foo', ['$scope',function ($scope) {
        $scope.delete = function(){
            bar($scope);
         }
    }]);

我试图通过使用 bind 使它更干净一些:

 app.controller('foo', ['$scope',function ($scope) {
        $scope.delete = bar.bind(null, $scope);
    }]);

不幸的是,这种形式没有按预期工作,并且 $scope 总是在绑定方法中提供旧版本的 $scope(此处为 bar),即使 $scope 已更改为 refer到不同的值。有什么问题吗?

还有什么?

如果我不应该在这里使用 bind,还有什么选择?

您确定 bar 没有使用 Util 中的任何内容吗?这样做:

app.controller('foo', ['$scope',function ($scope) {
    $scope.delete = Util.bar.bind(Util, $scope);
}]);

我假设您的问题是您的绑定 Util.bar 始终提供旧版本的 $scope,即使在 $scope 已更改为引用不同的值之后也是如此。

bind 绑定 ,而不是变量。您正在将 $scope 当前值绑定到 Util.bar。另一方面,每次函数运行时,您的第一种样式都会强制将标识符 $scope 解析为一个值(或者实际上是外部范围变量记录)。

如果 $scope 更改为引用完全不同的值,则必须使用第一种形式。 .bind(null, $scope) 将立即将 $scope 解析为一个值并永远使用该值,而没有 bind 的第一种形式将在每次函数运行时将 $scope 解析为一个值。

正如上面 apsillers 的回答中提到的,bind 方法在赋值时立即被评估 - 所以 $scope 的当前值被绑定为传递给 bar 函数的参数。至于 'cleaner' 替代方案,我不明白您为什么需要某些东西 'cleaner':您希望将 $scope.delete 分配为一个函数,该函数使用当前 $scope 值调用 bar ,你当前的代码对 T 做了什么。如果你仍在寻找更精简的代码,你总是可以采用 ES6 粗箭头语法(但你需要一个像 babel 这样的转译器) - 所以你的代码看起来像:

app.controller('foo', ['$scope',function ($scope) {
    $scope.delete = () => bar($scope);
}]);

看看这个 Plunker

   $scope.delete1 = function(){
      bar($scope);
   };

   $scope.delete2 = bar.bind(null, $scope);

   $scope.delete3 = function(){
      bar(this);
   };

对我来说,它的行为似乎完全符合预期:delete1 和 delete2 似乎在父控制器和子控制器上做同样的事情。 Delete 3 的行为不同——原因在这个答案中解释得很好:controller's scope

也许您可以准确指定您发现错误的行为(用例)。返回链接使您可以离开控制器页面,然后返回到控制器的新实例(和新范围 - 正如您从 $scope.$id 中看到的那样)。

正如@apsillers 所说,在绑定 $scope 中得到解析并在后续调用中使用,因此第一个方法是更简洁的方法,但如果您想使用绑定,则使用

app.controller('foo', ['$scope',function ($scope) { 
     $scope.delete = function(){ 
         bar.bind(null, $scope); 
     }
}]);