1. ホーム
  2. javascript

[解決済み] 変数の値を別の変数にコピーする

2022-11-09 12:42:52

質問

JSONオブジェクトを値として持つ変数があります。私はこの変数を他の変数に直接代入して、それらが同じ値を共有するようにしました。これはどのように動作するかです。

var a = $('#some_hidden_var').val(),
    b = a;

これは動作し、両方とも同じ値を持ちます。私は mousemove イベントハンドラを使って b を更新します。ボタンがクリックされたときに b に格納されている値を元の値に戻したい。 a .

$('#revert').on('click', function(e){
    b = a;
});

この後、同じように mousemove イベントハンドラを使用すると、両方の ab のみを更新していたのに、以前は b だけだったのが、予想通り

私はこの問題で困っています! 何が間違っているのでしょうか?

どのように解決するのですか?

を理解することが重要です。 = 演算子が何をし、何をしないかを理解することが重要です。

= 演算子は コピー を作成しません。

= 演算子は新しい 参照 を作成します。 同じ のデータに変換します。

元のコードを実行した後

var a = $('#some_hidden_var').val(),
    b = a;

a そして b は、現在では2つの異なる名前であり 同じオブジェクト .

このオブジェクトの内容に加えた変更は、このオブジェクトを a 変数で参照しても b という変数があります。これらは同じオブジェクトです。

そのため、後で "revert"しようとしたときに b を元の a オブジェクトに変換します。

b = a;

このコードでは実際に 何もしていません。 なぜなら ab は全く同じものです。と書いたのと同じようなコードです。

b = b;

というのは、明らかに何もしません。

なぜ新しいコードが動作するのでしょうか?

b = { key1: a.key1, key2: a.key2 };

ここでは、全く新しいオブジェクトを {...} オブジェクト・リテラルで新しいオブジェクトを作成しています。この新しいオブジェクトは、以前のオブジェクトと同じではありません。そのため、現在 b をこの新しいオブジェクトへの参照として設定することになり、これはあなたが望むことを行います。

任意のオブジェクトを扱うには、Armandの回答にあるようなオブジェクトクローン関数を使うか、jQueryを使っているので、単に $.extend() 関数 . この関数は、オブジェクトのシャローコピーとディープコピーのどちらかを作成します。(この関数と $().clone() メソッドと混同しないでください。 これはオブジェクトではなく DOM 要素のコピーのためのものです)。

浅いコピーのために

b = $.extend( {}, a );

ディープコピーでもいい。

b = $.extend( true, {}, a );

シャローコピーとディープコピーの違いは何ですか?シャローコピーは、オブジェクトリテラルを使用して新しいオブジェクトを作成するコードに似ています。これは、元のオブジェクトと同じプロパティへの参照を含む新しいトップレベルのオブジェクトを作成します。

オブジェクトが数値や文字列のような原始的な型のみを含む場合、ディープコピーとシャローコピーは全く同じことをします。しかし、オブジェクトの内部に他のオブジェクトや配列がネストされている場合、シャローコピーでは コピー しかし、オブジェクトの中に他のオブジェクトや配列がネストされている場合、シャローコピーはそれらのネストされたオブジェクトをコピーするのではなく、単にそれらへの参照を作成するだけです。そのため、ネストされたオブジェクトに対して、トップレベルのオブジェクトと同じ問題が発生する可能性があります。例えば、このようなオブジェクトがあるとします。

var obj = {
    w: 123,
    x: {
        y: 456,
        z: 789
    }
};

そのオブジェクトのシャローコピーを行う場合は x プロパティは、新しいオブジェクトの同じ x オブジェクトになります。

var copy = $.extend( {}, obj );
copy.w = 321;
copy.x.y = 654;

これで、あなたのオブジェクトは次のようになります。

// copy looks as expected
var copy = {
    w: 321,
    x: {
        y: 654,
        z: 789
    }
};

// But changing copy.x.y also changed obj.x.y!
var obj = {
    w: 123,  // changing copy.w didn't affect obj.w
    x: {
        y: 654,  // changing copy.x.y also changed obj.x.y
        z: 789
    }
};

ディープコピーを使えば、これを避けることができます。ディープコピーは、ネストされたすべてのオブジェクトと配列(ArmandのコードではDate)に再帰し、トップレベルのオブジェクトのコピーを作成したのと同じ方法で、それらのオブジェクトのコピーを作成します。そのため copy.x.y を変更しても obj.x.y .

短い答えです。迷ったら、おそらくディープコピーが必要でしょう。