2016-05-17 9 views
4

Sprache: Javascript
Betriebssystem: Ubuntu 14.04
Browser: Getestet in Chrom, Chrome, Firefox.Wie binde ich den Parameter 'this' an jedes Element eines Arrays, wenn forEach() verwendet wird?

Hintergrund

ich ein HTML5 Canvas Spiel mache, dass verschiedene Sammlerstücke hat. Die übergeordnete Klasse für diese Elemente ist Collectable, das hat eine render() Funktion:

Collectable.prototype.render = function(){ 
    // renders the collectables 
} 

Es gibt verschiedene Unterklassen von Collectable, von denen alle Delegierten render() an der übergeordneten Klasse. Zum Beispiel:

var Heart = function(x, y) { 
    Collectable.call(this, x, y); 
} 
Heart.prototype = Object.create(Collectable.prototype); 

I instanziiert meine Sammler, indem zuerst alle meine Sammler Erstellen eines Arrays enthält:

var collectables = []; 
var numOfEach = 5; 
// IIFE so as to not pollute global scope 
(function() { 
    for (var i = 0; i < numOfEach; i++) { 
     // TODO: make this cleaner 
     var heart = new Heart(100, 200); 
     collectables.push(heart); 
     var gemBlue = new GemBlue(100, 200); 
     collectables.push(gemBlue); 
     var gemOrange = new GemOrange(100, 200); 
     collectables.push(gemOrange); 
    } 
})(); 

Dann in meinem Spiel Loopdatei, ich habe eine renderEntities() Funktion, die immer wieder einzelne Anrufe Methoden machen meine Objekte auf:

function renderEntities() { 
    // render my other objects 
    ... 

    // render collectables 
    collectables.forEach(function() { 
     // test what 'this' is bound to 
     console.log(this); 

     // call render method 
     this.render(); 
    }); 
} 

... aber in diesem Fall ist this zu window gebunden und dafür e this.render ist keine Funktion.

Frage

Wie binde ich this auf jedes einzelne Element meiner collectables Array?

Meine Forschung

ich die documentation for the bind function gelesen habe, aber ich fürchte, ich kann Sie nicht arbeiten, wie dies mit forEach() und meiner anonymen Funktion angewandt werden würde.

Ich fand dann this existing question, die erläutert, wie forEach einen optionalen Parameter zu this setzt. Nach den documentation on forEach Lesen habe ich versucht, die folgende mit erfolglosen Ergebnissen:

collectables.forEach(function() { 
    // test what 'this' is bound to 
    console.log(this); 

    // call render method 
    this.render(); 
}, this); 

... was natürlich die gleiche Wirkung hatte this auf das globale Objekt zu setzen.

collectables.forEach(function() { 
    // test what 'this' is bound to 
    console.log(this); 

    // call render method 
    this.render(); 
}, collectables); 

... das hat mir ein wenig näher, als this zum Sammler Array als Ganzes gebunden ist, aber offensichtlich this.render ist noch keine Funktion. Ich kann nicht sehen, welches Argument ich hier in forEach verwenden kann, um this an jedes Element des Arrays zu binden.

Ich habe das Gefühl, dass nach der Eingabe all dies die Antwort sehr einfach sein wird. Ich bin relativ neu in dem Konzept von this so gehen Sie einfach auf mich!

Ich habe keine andere Frage gefunden, die das für mich beantwortet, oder zumindest eine, die ich angesichts meines Wissensstandes verstehen kann. Zum Beispiel habe ich folgende Fragen betrachtet:

+0

try 'collectables.forEach.call (Sammler, Rückruf) ' –

+1

Sind Sie daran interessiert, das Schlüsselwort' this' gezielt zu verwenden? Es scheint, als würde Ihr Beispiel funktionieren, wenn Sie das Array-Element als Teil des 'forEach'-Callbacks eingefügt haben. Zum Beispiel, 'collectibles.forEach (function (collectible) {collectible.render();});' – Himmel

+0

Hätte nicht jedes Objekt, das an den 'forEach'-Callback übergeben wurde, Zugriff auf die 'render'-Methode? In diesem Fall brauchen Sie "this" nicht wirklich im Callback. –

Antwort

1

Die .forEach() Anlage werden drei Argumente an Ihre Callback-Funktion:

  1. Das aktuelle Element des Arrays;
  2. Der Index in das Array;
  3. Das Array selbst.

So:

collectibles.forEach(function(collectible) { 
    // the parameter "collectible" will be the 
    // current array element 
}); 

Es gibt wirklich keine Notwendigkeit, this zu binden, aber wenn Sie unbedingt man wollte konnte:

collectibles.forEach(function callback(collectible) { 
    if (this !== collectible) 
    callback.call(collectible, collectible); 
    else { 
    // body of function 
    } 
}); 
+0

Ja, peinlich einfach. Ich war so auf "dieses" konzentriert, dass ich übersehen hatte, wie "forEach" funktioniert. – andydavies

4

Wenn ich richtig verstehe, Sie schauen, um das Objekt in Verbindung mit jedem sammelbare Einzelteil zu erhalten. Übergeben Sie in diesem Fall einfach ein Argument für die forEach-Schleife. In diesem Fall habe ich dieses Argument theObj genannt, aber vielleicht theCollectable oder sogar nur c wäre genauer.

collectables.forEach(function(theObj) { 
    // test what 'this' is bound to 
    console.log(theObj); 

    // call render method 
    theObj.render(); 
}); 

Update: die this Sie im forEach Anruf Passieren der aktuelle Wert von this an die Schleife übergeben. An diesem Punkt wird this im Rahmen von window ausgeführt, und deshalb ist thiswindow. Sie müssen this nicht übergeben, wenn Sie nicht auf das Fenster verweisen möchten, und da window global ist, müssen Sie wirklich this überhaupt nicht passieren, also habe ich es von der vorgeschlagenen Antwort entfernt.

Update: die MDN ist eine großartige Ressource für JavaScript-Dokumentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

+1

Sie haben Recht. Ich habe die andere Antwort akzeptiert, nur weil sie die Frage technisch beantwortet hat (in Bezug auf "das"). Der Fehler gehört mir, eine fehlerhafte Frage zu stellen! – andydavies

+1

Es war eine gültige Frage :) –