2012-05-08 5 views
0

私は、javascriptクロージャー内で非常に奇妙な動作に遭遇しました。クロージャのグローバル変数がオブジェクトである場合、その変数から別の変数への代入は何らかのポインタのように動作します。簡単なコードは、私が何を意味するか、より良い説明する必要があります:クロージャー内のオブジェクトへの割り当ては、ポインタのように振る舞います

function closure() {  
    var foo = {key1 : 'value 1'}; 
    return { 
    method: function(){ 
     var bar = foo; 
     bar.key2 = 'value2'; 
     return 'foo has attributes : ' + foo.key1 + ' and ' + foo.key2 
    } 
    } 
} 
var someVar = closure(); 
someVar.method(); // returns "foo has attributes : value 1 and value2" (!!!) 

私は明らかとしてのみbarが変更されました...しかし、スクリプトが実際に両方barfooを変更する私をたくさん混乱foo has attributes : value 1 and undefinedを得ることが期待されます。

私もfoobarは、文字列や数値であるとき、すべてが期待どおりに動作することに気づいた - barを変更することはfooには影響しません。

function closure() { 
    var foo = 10; 
    return { 
    method: function(){ 
     var bar = foo; 
     bar += 1; 
     return 'foo is : ' + foo + ' and bar is ' + bar 
    } 
    } 
} 
var someVar = closure(); 
someVar.method(); // returns "foo is : 10 and bar is 11" 

私はこの行動の理由...運を把握しようと、全夜を過ごしました。 SpiderMonkeyとV8(Chromeとnode.jの両方)と同じ結果が得られました。

私がしたいことはもちろん、fooに影響を与えずに最初の例からbarを修正することです。どんな助けも非常に高く評価されます。

+0

この予想される動作は、実際にはクロージャとは関係ありません。あなたの説明のために – dlaliberte

答えて

2

var bar = foo;を実行すると、barfooの両方が同じオブジェクトを指しています。 fooを変更しない場合は、クローンfooが必要です。クローンを作成すると、全く新しいオブジェクトが作成され、barがそれを指し示します。 This answerには、Javascriptでのオブジェクトの複製に関する情報があります。

また、この動作はクロージャに限定されません。通常のJavaScriptコードで発生します:プロパティabcを持つよう

var foo = {a: 10, b: 6}; 
var bar = foo; 
bar.c = 7; 
console.log(foo); 

fooが表示されます。

あなたが見ているのは、ほとんどのオブジェクト指向言語の標準的な動作です。オブジェクトを扱うときは、具体的なインスタンス値の代わりに参照をそれらのオブジェクトに対して処理しています。 Javascriptではプリミティブ型なので数字では表示されないので、それらの値を参照するのではなく実際の値を扱います。

+1

おかげで!どのように私の問題があったか驚きました:) – lukaszfiszer

2

これは、ほぼすべてのオブジェクト指向言語の動作が期待される、まったく正常な動作です。変数は、オブジェクト自体ではなく、オブジェクトへの参照を保持します。それはポインタのようですが、メモリの場所の詳細から抽象化されています。あなたはそれや何かの算術演算を行うことはできません。それを使用する限り、変数がオブジェクトを直接保持しているように見えますが、そうではありません。オブジェクトを関数に渡すと、JavaScriptが値渡しであっても、その関数がオブジェクトを変更できます。そして、別の変数に代入すると、コピーは得られませんが、別名は同じオブジェクトを指す2つの変数です。

コピーを作成する場合は、明示的に行う必要があります。自動的に組み込む方法はありませんが、いくつかのオプションについてはthis questionを参照してください。

+1

あなたの助けに感謝!私はまだ多くのことを学んでいると思います! – lukaszfiszer

関連する問題