2016-07-02 3 views
0

Ich habe mich selbst ein bisschen verrückt fahren versucht, herauszufinden, wie dieser Code funktioniert. Mein Ziel ist es, den Ausgang larry eats pie, larry eats candy, larry eats cake durch Binden der Funktion eats innerhalb des Objekts alice an das Objekt larry zu erzeugen. Meine Hoffnung mit dem Code unten war, dass Bindung der alice.eats Funktion an das Larry-Objekt larry als this.name verwenden würde, und anschließend diese Funktion mit einem Array von larryFoods anwenden, würde ich hoffen, dass es larry eats + [food] für jedes Argument produzieren würde.Binding-Funktionen in Javascript, die im globalen Kontext funktionieren

//-----------------Does not work--------------// 
var alice = { 
     name: "alice", 
     speak: function(){ 
     console.log("Hi, I'm " + this.name); 
     }, 
     eats : function(){ 
     var theArgs = Array.prototype.slice.call(arguments); 
     theArgs.forEach(function(arg){ 
      console.log(this.name + " eats " + arg); 
     }); 
     } 
}; 
var larry = { 
    name: "larry" 
}; 
var larrySpeak = alice.speak.bind(larry); 
larrySpeak(); 
var larryFoods = [" pie", " candy", " and cake"]; 
var larryEats = alice.eats.bind(larry); 
larryEats.apply(larryFoods); 

Ich gehe davon aus, dass die forEach Funktion im globalen Kontext arbeitet, weshalb ich bind hatte gehofft, das Problem lösen würde. Jeder Einblick wäre sehr willkommen.

+0

Beachten Sie, dass die 'forEach' Rückruf ein neues' this' hat, so dass Sie den Kontext dort verloren. – elclanrs

Antwort

1

this ist nicht auf die "Person" innerhalb Ihrer forEach in der Funktion beschränkt. Oder optisch:

theArgs.forEach(function(arg){ 
    // "this".name is trying to resolve name according to the scope of the forEach 
    console.log(this.name + " eats " + arg); 
}); 

Sie können dieses Problem beheben, wie diese innerhalb der eats Funktion:

var scope = this; 
theArgs.forEach(function(arg){ 
    console.log(scope.name + " eats " + arg); 
}); 

Schließlich müssen Sie Ihre Nutzung von apply in der allerletzten Zeile beheben. apply benötigt einen Kontext zum Binden. Da Sie bereits die Funktion larry gebunden, können Sie einfach null als erstes Argument übergeben:

Dieses:

larryEats.apply(larryFoods); 

sein sollte:

larryEats.apply(null, larryFoods); 

Nachdem diese Dinge Festsetzung Hier ein Arbeitsbeispiel:

var alice = { 
 
    name: "alice", 
 
    speak: function() { 
 
    console.log("Hi, I'm " + this.name); 
 
    }, 
 
    eats: function() { 
 
    var theArgs = Array.prototype.slice.call(arguments); 
 
    var scope = this; 
 
    theArgs.forEach(function(arg) { 
 
     console.log(scope.name + " eats " + arg); 
 
    }); 
 
    } 
 
}; 
 
var larry = { 
 
    name: "larry" 
 
}; 
 
var larrySpeak = alice.speak.bind(larry); 
 
larrySpeak(); 
 
var larryFoods = ["pie", "candy", "and cake"]; 
 
var larryEats = alice.eats.bind(larry); 
 
larryEats.apply(null, larryFoods);

0

Dies funktioniert für mich:

var alice = { 
     name: "alice", 
     speak: function(){ 
     console.log("Hi, I'm " + this.name); 
     }, 
     eats : function(){ 
     var theArgs = Array.prototype.slice.call(arguments); 
     let that = this; 
     theArgs.forEach(function(arg){ 
      console.log(that.name + " eats " + arg); 
     }); 
     } 
}; 
var larry = { 
    name: "larry" 
}; 
var larrySpeak = alice.speak.bind(larry); 
larrySpeak(); 
var larryFoods = [" pie", " candy", " and cake"]; 
var larryEats = alice.eats; 
larryEats.apply(larry, larryFoods); 
Verwandte Themen