2015-06-09 7 views
9

Il seguente controller funziona senza problemi.Il metodo `bind` di JavaScript non funziona come previsto

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

ho cercato di renderlo un po 'più pulito utilizzando bind:

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

Purtroppo, questa forma non funziona come previsto e $scope è sempre fornito con una vecchia versione di $ portata in metodo associato (bar qui), anche dopo che $ scope è stato cambiato in riferimento a un valore diverso. Cosa c'è che non va?

Cos'altro?

Se non dovrei usare bind qui, qual è l'alternativa?

+0

Cosa c'è dentro Util? Non riesco a pensare perché dovresti farlo. –

+1

Sembra abusare di legarmi a me. –

+1

È il problema che un valore * è * viene fornito a '$ scope.delete', ma è un * vecchio * valore? O la funzione fallisce completamente (o non viene fornito un valore)? – apsillers

risposta

10

Suppongo che il tuo problema è che il vostro limite Util.bar è sempre fornito con una vecchia versione di $scope, anche dopo $scope è cambiato per riferirsi a un valore diverso.

bind binds valori, non variabili. Si sta vincolando il valore corrente di $scope a Util.bar. D'altra parte, il tuo primo stile forza l'identificatore $scope a essere risolto su un valore (o, in realtà, un record di variabile esterno) ogni volta che viene eseguita la funzione.

Se $scope cambia per fare riferimento a un valore completamente diverso, è necessario utilizzare il primo modulo. .bind(null, $scope) risolverà immediatamente il valore $scope e utilizzerà tale valore per sempre, mentre il primo modulo senza bind risolverà $scope in un valore ogni volta che viene eseguita la funzione.

+0

Grazie, Qual è il metodo alternativo per i secondi codici. – PHPst

+0

@PHPst L'alternativa è ciò che stai già facendo nel tuo primo esempio. Puoi modificare per spiegare perché non è sufficiente? – apsillers

+0

come @apsillers detto in 'bind' $ viene risolto e usato nelle chiamate successive in modo più pulito è prima, ma si vuole ancora associare quindi usare questo app.controller ('foo', ['$ scope', function ($ scope) { $ scope.delete = function() {bar.bind (null, $ scope);} }]); – vinayakj

2

Sei sicuro che bar non utilizza nulla da Util? Fare questo:

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

Come menzionato nella risposta sopra descritta, il metodo di associazione viene immediatamente valutato al momento dell'assegnazione, quindi il valore corrente di $ scope è associato come argomento da passare alla funzione della barra. Per quanto riguarda un'alternativa "più pulita", non vedo perché hai bisogno di qualcosa di "più pulito": stai cercando di assegnare $ scope.delete come una funzione che richiama la barra con il valore $ scope corrente, che il tuo codice attuale fa ad un T. Se siete ancora alla ricerca di qualcosa di un po 'di codice più snello saggio si può sempre adottare ES6 sintassi grasso freccia (ma avresti bisogno di un transpiler come babel) - così il vostro codice sarà simile:

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

Dai un'occhiata a questo Plunker.

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

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

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

A me sembra comportarsi esattamente come dovrebbe: delete1 e delete2 sembrano fare la stessa cosa su entrambi i controller di genitore e figlio. Elimina 3 si comporta in modo diverso - il motivo è spiegato molto bene in questa risposta: controller's scope

Forse è possibile specificare esattamente quale comportamento (usecase) si trova sbagliato. I link di ritorno sono così che puoi lasciare la pagina del controller e poi tornare alla nuova istanza del controller (e un nuovo scope - come puoi vedere da $ scope. $ Id).

-1

come @apsillers detto, nella legatura $ portata viene risolto e viene utilizzato nelle chiamate successive, in modo da modo più pulito è il primo, ma ancora Se si desidera utilizzare bind quindi utilizzare

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

Quando viene chiamato 'delete', crea semplicemente un valore di funzione che viene buttato via. –