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" (!!!)

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

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.js の両方) で同じ結果が得られました。

私がやりたいことはもちろん、foo に影響を与えずに最初の例から bar を変更することです。どんな助けでも大歓迎です。

4

2 に答える 2

2

を実行すると、とvar bar = foo;の両方が同じオブジェクトを指しています。変更したくない場合は、クローンを作成する必要があります。複製すると、まったく新しいオブジェクトが得られ、それを指します。この回答には、Javascript でのオブジェクトの複製に関する情報が含まれています。barfoofoo foobar

また、この動作は閉鎖に限定されません。これは、通常の Javascript コードで発生します。

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

、、およびfooのプロパティを持つものとして表示されます。ab c

ご覧になっているのは、ほとんどのオブジェクト指向言語の標準的な動作です。オブジェクトを扱うときは、特定のインスタンス値ではなく、それらのオブジェクトへの参照を扱っています。Javascript ではプリミティブ型であるため、数値ではこれが表示されないため、これらの値への参照ではなく、実際の値を扱っています。

于 2012-05-08T23:28:08.900 に答える
2

これは、ほぼすべてのオブジェクト指向言語、確かに私が考えることができるすべての動的言語の完全に正常な動作です。変数は、オブジェクト自体ではなく、オブジェクトへの参照を保持します。これはポインタに似ていますが、メモリ位置の詳細から離れて抽象化されています。あなたはそれに対して算術を行うことはできません。それを使用する限り、変数はオブジェクトを直接保持しているように見えますが、そうではありません。オブジェクトを関数に渡すと、JavaScript が値渡しであっても、その関数はオブジェクトを変更できます。また、それを別の変数に割り当てると、コピーではなくエイリアスが得られます。つまり、同じオブジェクトを指す 2 つの変数です。

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

于 2012-05-08T23:30:59.170 に答える