2017-05-19 4 views
0

Ich habe eine Funktion, die ich für einen Konstruktoraufruf ...Warum wird die Eigenschaft meines Objekts in JavaScript nicht aktualisiert?

function Queue() { 
    if (!(this instanceof Queue)) return new Queue(); 
    this.capacity = {}; 
    this._count = 0; 
} 

Und diese Verfahren werden auf dem die Eigenschaft prototype Queue ... Alles koscher richtige Set vorbereitet haben?

Queue.prototype.enqueue = function(name, options) { 
    this.capacity[name] = options || {}; 
    this.count(); 
    if (this._count > 5) { 
     return 'Max capacity has been reached—which is five, please dequeue....' 
    } 
    }; 

    Queue.prototype.count = function() { 
    var total = Object.keys(this.capacity); 
     total.forEach(function(elem) { 
     this._count++ 
     }); 
     if (this._count == 1) { 
     console.log(this.capacity[Object.keys(this.capacity)]) 
     console.log('There is one item in the queue'); 
     } else { 
     console.log(this.capacity[Object.keys(this.capacity)]) 
     console.log('There are ' + this._count + ' items in the queue'); 
     } 
    }; 

Meine Frage wie bekomme ich this._count zu erhöhen, wenn die enqueue/Zählverfahren Feuer? Ich erhalte:

There are 0 items in the queue 

Ich weiß, dass ich es auf dem .prototype Eigenschaft hinzufügen könnte und legen Sie, dass in der Zählfunktion und haben eine lokale var Referenz ...

Queue.prototype.count = function() { 
    var total = Object.keys(this.capacity), count = 0; 
    total.forEach(function(elem) { 
     this.count++ 
    }); 

Queue.prototype.call = Ruf // < - komisch nein?

if (this.count == 1) { 
    console.log(this.capacity[Object.keys(this.capacity)]) 
    console.log('There is one item in the queue'); 
} else { 
    console.log(this.capacity[Object.keys(this.capacity)]) 
    console.log('There are ' + this.count + ' items in the queue'); 
} 

};

Aber das scheint nicht elegant zu sein ...

Vielen Dank im Voraus!

+0

Sie könnten zu 'this._count + = Object.keys (thiscapacity) .length' vereinfachen. Und meinst du nicht, '_count' auf null zurückzusetzen oder' '' anstelle von '+ =' zu benutzen? –

Antwort

2

Sie müssen dies

Queue.prototype.count = function() { 
    var total = Object.keys(this.capacity); 
     total.forEach(function(elem) { 
     this._count++ 
     }.bind(this)); //bind the context 
     if (this._count == 1) { 
     console.log(this.capacity[Object.keys(this.capacity)]) 
     console.log('There is one item in the queue'); 
     } else { 
     console.log(this.capacity[Object.keys(this.capacity)]) 
     console.log('There are ' + this._count + ' items in the queue'); 
     } 
    }; 
+0

oder verwenden Sie eine Pfeilfunktion mit lexikalischer Bindung oder einfach das veraltete 'var self = this;' und verwenden Sie 'self' im Callback. –

+1

Einverstanden. Es gibt viele Lösungen. Aber ich schätze, der Benutzer möchte, dass die Lösung in IE10, IE11 funktioniert. Ansonsten hätte er die ES6-Syntax überall verwendet. – karthick

1

Versuchen folgende Modifikation innerhalb forEach binden (bindet die Funktion):

total.forEach(function(elem) { 
    this._count++ 
}.bind(this)); 

Die Probleme ist, dass this auf ein anderes Objekt verweist, als in der übergeordneten Funktion, weil in JS, Verschlüsse this nicht beibehalten, sondern stattdessen der Anrufer den this Wert entscheidet. Alternativ können Sie das zweite thisArg Argument von foreach verwenden.

1

Die vorhandenen Antworten bieten gute Lösungen für das Problem selbst, ich dachte nur, ich würde ein bisschen mehr auf das Warum eingehen.

this ist eine Referenz, die vom Ausführungskontext zugewiesen wird. Genauer gesagt ist es eine Referenz, die durch die Aufrufseite der Funktion bestimmt wird. Da Sie Funktionen in JavaScript wie jeden anderen Wert weitergeben können, kann dies dazu führen, dass diese Referenz ein bewegliches Ziel ist.

Das Problem mit Ihrem Code ist, dass Sie sich auf this innerhalb einer forEach beziehen. forEach nimmt eine Funktion als Argument und ruft sie auf, denn was auf this zeigt, wird durch den Ort bestimmt, an dem die Funktion aufgerufen wird, und nicht dort, wo sie definiert ist, ist der Wert etwas anders, wenn sie aufgerufen wird. Es endet damit, dass Sie in den globalen Kontext zurückfallen oder undefiniert, wenn Sie sich im strikten Modus befinden.

Es gibt verschiedene Möglichkeiten, das Problem zu lösen.

Sie könnten einen Verweis auf die äußere this auf einer Variablen speichern und in der anderen Funktion verwenden.

var self = this; 
total.forEach(function(elem) { 
    self._count++; 
}); 

Sie könnten .bind verwenden. Es ist eine Funktionsmethode, die eine Funktion zurückgibt, die das übergebene Objekt als Referenz für this verwendet, egal wo Sie es aufrufen.

total.forEach(function(elem) { 
    this._count++; 
}.bind(this)); 

Oder Sie könnten eine Pfeilfunktion verwenden. Pfeilfunktionen erstellen keinen eigenen Kontext, so dass sie nur den Wert this von dem umgebenden beibehalten.

total.forEach(() => { 
    this._count++; 
}); 

Dies ist ein häufiges Problem und das sind alle gültigen Lösungen. Sie gehen meiner Meinung nach am wenigsten elegant aus.

Verwandte Themen