2016-04-01 6 views
0

私はいくつかのデフォルトプロパティを持つJSクラスを持っています。デフォルトオブジェクトとデフォルトオブジェクトをオーバーライドするオプションオブジェクトを渡すことができます。私はこれを達成するために私のコンストラクタでlodashのextendメソッドを使用しています。lodashのextendメソッドを使用してJSオブジェクトインスタンスを拡張すると奇妙な結果が発生します

デフォルトのプロパティの1つが配列です。最初のインスタンスをインスタンス化して配列に新しい値をプッシュすると、2番目のオブジェクトをインスタンス化すると、デフォルトの配列には最初のインスタンスにプッシュされたオブジェクトが含まれます。

例えば、このコードを取る

...

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]} 

私はmySecondObj.myArrは空の配列であることを期待しています。

myObj.myArrに値をプッシュすると、どういうわけかdefaults.myArrが変更され、クラスの後続のインスタンスに使用されますか?

答えて

3

defaultsからthisまでのオブジェクトプロパティを_.extendとマージすると、単に配列への参照が作成されます。したがって、あるインスタンスの配列参照が更新されると、すべての参照がその変更を反映します。

あなたはこれを回避するために、オブジェクトのクローンを作成できます。

_.cloneDeep(defaults) 

DEMO

それとも単純にコンストラクタを使用します。

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

ありがとうございます。これは、閉鎖に関するコメントに加えて、理にかなっています。 –

1

シンプルプットを:あなたが作成しましたclosure

あなたが別の関数を作成し、あなたの自己実行機能の中に、あなたはそれを継承defaultsを作成した関数は親の自己実行機能だ、あなたはMyClassに関数を返すとき、任意のオブジェクトの作成には、これらのデフォルト設定については、同一の参照を持つことになります(the defaults object )、あなたがクラスを作成するたびに作成されるオブジェクトはdefaultsなので、常に同じものです。

関連する問題