Метод JavaScript ' bind` не работает должным образом

следующий контроллер работает без проблем.

 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 для ссылки на другое значение. Что с ним не так?

что еще?

если я не должен использовать bind здесь, какова альтернатива?

5 ответов


я предполагаю, что ваша проблема в том, что ваша граница Util.bar всегда поставляется со старой версией $scope, даже после $scope изменилось, чтобы ссылаться на другое значение.

bind персонализация значения, а не переменные. Вы связываете текущее значение $scope to Util.bar. С другой стороны, ваш первый стиль заставляет идентификатор $scope быть разрешенным к значению (или, действительно, записи переменной внешней области) каждый раз, когда функция работает.

если $scope изменения чтобы ссылаться на совершенно другое значение, необходимо использовать первую форму. .bind(null, $scope) решить $scope значение сразу и использовать это значение навсегда, в то время как первая форма без bind решить $scope до значения при каждом запуске функции.


посмотри Plunker .

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

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

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

Мне кажется, что он ведет себя точно так, как должен: delete1 и delete2, похоже, делают то же самое на родительском и дочернем контроллере. Delete 3 ведет себя по - другому-причина объясняется очень красиво в этом ответе:контроллер

возможно, вы можете точно указать, какое поведение (usecase) вы найдете неправильным. Ссылки возврата назад таковы, что вы можете оставить страницу контроллера, а затем вернитесь к новому экземпляру контроллера (и новой области-как вы можете видеть из $scope.$идентификатор.)


вы уверены bar не использует ничего из Util? Этого:

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

Как упоминалось в ответе apsillers выше, метод bind немедленно оценивается при назначении - поэтому текущее значение $scope связано как аргумент для передачи функции bar. Что касается "более чистой" альтернативы, я не понимаю, почему вам нужно что-то "более чистое": вы хотите назначить $scope.удалить как функцию, которая вызывает bar с текущим значением $ scope, которое ваш текущий код делает с T. Если вы все еще ищете что-то немного более скудный код, вы всегда можете принять синтаксис ES6 fat arrow (но вам понадобится транспилер, такой как babel) - так что ваш код будет выглядеть так:

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

Как сказал @apsillers, в bind $scope разрешается и используется в последующих вызовах,поэтому более чистый способ является первым, но все же, если вы хотите использовать bind, используйте

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