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);
}
}]);
以下控制器工作正常。
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);
}
}]);