2016-04-01 4 views
0

Ich habe eine JS-Klasse, die einige Standardeigenschaften hat. Ich möchte in der Lage sein, ein Optionen-Objekt übergeben, um die Standardeinstellungen sowie einige zusätzliche, die nicht standardmäßig sind. Ich verwende lodash extend Methode in meinem Konstruktor, um dies zu erreichen.Die Erweiterung der JS-Objektinstanz mit der extend-Methode von lodash verursacht seltsame Ergebnisse

Eine der Standardeigenschaften ist ein Array. Wenn ich die erste Instanz instanziiere und einen neuen Wert in das Array verschiebe, wenn ich das zweite Objekt instanziiere, enthält das Standardarray das Objekt, das ich in die erste Instanz geschoben habe.

diesen Code Nehmen Sie zum Beispiel ...

MyClass = (function() { 
    var defaults = { 
    myArr: [], 
    myProp: 'I\'m a default value' 
    }; 

    function MyClass(options) { 
    // console.log(defaults) 
    if(typeof options === 'object') { 
     return _.extend(this, defaults, options); 
    } 
    else { 
     return _.extend(this, defaults); 
    } 
    } 

    return MyClass; 
})(); 

var myObj = new MyClass({foo: 'bar'}) 
myObj.myArr.push('baz') 
var mySecondObj = new MyClass(); 
console.log(mySecondObj) // MyClass {myArr: Array[1]} 

Ich erwarte, dass mySecondObj.myArr ein leeres Array sein.

Wie ist es, dass, wenn ich einen Wert in , defaults.myArr irgendwie geändert wird und für nachfolgende Instanzen der Klasse verwendet wird?

Antwort

3

Wenn Sie die Objekteigenschaften von defaults mit this mit _.extend zusammenführen, erstellen Sie lediglich einen Verweis auf das Array. Wenn also die Array-Referenz in einer Instanz aktualisiert wird, spiegeln alle Referenzen diese Änderung wider.

Sie könnten das Objekt klonen, dies zu umgehen:

_.cloneDeep(defaults) 

DEMO

Oder verwenden Sie einen einfachen Konstruktor:

function MyClass(options) { 
    var defaults = { 
    myArr: [], 
    myProp: 'I\'m a default value' 
    } 
    if (typeof options === 'object') { 
    _.extend(this, defaults, options); 
    } else { 
    _.extend(this, defaults); 
    } 
} 

DEMO

+0

Danke an alle. Dies ist neben dem Kommentar zur Schließung durchaus sinnvoll. –

1

Einfach ausgedrückt: Sie erstellt eine closure.

In Ihrem self-executing Funktion erstellen Sie eine andere Funktion, die Funktion, die Sie erben defaults von ihm erstellt ist Eltern-self-executing Funktion, wenn Sie die Funktion MyClass jede Objekterstellung zurückkehren wird die gleiche Referenz für die Standardwerte haben (the defaults object), es gibt kein defaults Objekt, das jedes Mal erstellt wird, wenn Sie eine Klasse erstellen, und deshalb ist es immer dasselbe.