9
votes

La méthode JavaScript `Bind` ne fonctionne pas comme prévu

Le contrôleur suivant fonctionne sans problème.

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


11 commentaires

Qu'est-ce qui est à l'intérieur jusqu'à ce que? Je ne peux pas penser à pourquoi auriez-vous besoin de le faire?


Semble une mauvaise utilisation de me lier.


Est le problème qu'une valeur est être fournie à $ étendue.delete , mais c'est une valeur ancienne Ou la fonction est-elle tout simplement échouée (ou ne pas être fournie du tout)?


@Shawnerquhart Qu'est-ce qui te fait penser?


@Asillers "... Les modifications de $ de portée ne sont pas envoyées à la méthode contraignée (barre ici)."


@zeroflagl Il l'utilise pour la propreté de code, pas pour définir explicitement 'ceci'.


@ShawnerQuhart Définition d'une valeur pour Ce n'est pas le seul cas d'utilisation valide. Après tout, il s'appelle Bind , pas setThisarg .


@Phpst Veuillez modifier ce message pour inclure un MCVE


Le comportement que vous décrit est le attendu pour moi, car vous éliminez la fermeture de cette méthode avec BIND (NULL ...) Je sais que je ne m'en aidons pas beaucoup, mais je recommanderais de vérifier comment les objets de référence sont passés En JavaScript, comment fonctionne la fermeture en JavaScript et quelle est la méthode de la méthode. Je suppose qu'après que vous comprendrez exactement pourquoi le contexte $ n'est pas mis à jour Conseil: sans fermeture que VAR n'est plus lié à la méthode.


Qu'essayez-vous de faire avec la portée avant d'appeler Supprimer ? Je suis spécifiquement intéressé par les propriétés que vous définissez. Souhaitez-vous partager du code ou pseudocode illustrant l'affaire?


"Après $ de portée a changé pour se référer à une valeur différente". Êtes-vous réellement contraignant $ étendue à une valeur différente (i.e. $ étendue = {}; )? Dans ce cas, Supprimer sera toujours au courant de la valeur de $ de portée était à l'exécution. Si vous avez besoin de la valeur au moment de l'appel, vous devrez conserver la fonction d'emballage. Si seulement une propriété de $ étendue change, alors Supprimer doit lire la valeur actuelle au moment de l'appel.


5 Réponses :


2
votes

êtes-vous sûr que bar code> n'utilise rien à partir de util code>? Faites ceci:

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


0 commentaires

10
votes

Je suppose que votre problème est que votre lié util.bar est toujours fourni avec une ancienne version de $ étendue , même après $ de portée > a changé pour se référer à une valeur différente.

BIND LIENS Valeurs , pas variables. Vous liez la valeur actuelle de $ de portée à util.bar . D'autre part, votre premier style force l'identifiant $ de portée à résoudre à une valeur (ou, vraiment, enregistrement de variable externe-portée) chaque fois que la fonction fonctionne.

Si $ étendue Modifications Pour faire référence à une valeur complètement différente, vous devez utiliser le premier formulaire. .bind (null, $ périmètre) résoudre $ étendue à une valeur immédiatement et utilisez cette valeur pour toujours, tandis que le premier formulaire sans lier sera résoudre $ portée à une valeur chaque fois que la fonction fonctionne.


3 commentaires

Merci, quelle est la méthode alternative pour les deuxième codes.


@Phpst L'alternative est ce que vous faites déjà dans votre premier exemple. Pouvez-vous modifier pour expliquer pourquoi cela n'est pas suffisant?


Comme @Asillers a dit dans Bind $ DMARTURE obtenue et est utilisé dans les appels ultérieurs Nettoyant Way est d'abord mais que vous souhaitez toujours lier, utilisez cette application.Controller ('"$ de portée', fonction ('" $ étendue) {$ portée.delete = fonction () {bar.bind (null, $ étendue);}}]);



1
votes

Comme mentionné dans Afsillers Répondez ci-dessus, la méthode de liaison est immédiatement évaluée lors de l'affectation - de sorte que la valeur actuelle de $ de portée est liée comme argument à transmettre à la fonction de barre. En ce qui concerne une alternative «plus propre», je ne vois pas pourquoi vous avez besoin de quelque chose de «nettoyant»: vous souhaitez affecter $ SCPORT.Delete en tant que fonction qui invoque la barre à la valeur actuelle $, que votre code actuel à un T. Si vous cherchez toujours quelque chose d'un code plus maigre sage, vous pouvez toujours adopter la syntaxe ES6 Frow arrow (mais vous auriez besoin d'un transpilateur comme Babel) - de sorte que votre code ressemblerait à:

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


0 commentaires

4
votes

Regardez sur ce PLUCKER .

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

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

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


0 commentaires

-1
votes

Comme @Asillers a dit, dans la liaison $ Domaine est résolu et est utilisé dans des appels ultérieurs, de manière plus propre, c'est le premier à nettoyer, mais toujours si vous souhaitez utiliser Bind, utilisez

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


1 commentaires

Lorsque Supprimer est appelé, cela crée simplement une valeur de fonction qui est jetée.