25

JavaScript でオブジェクトをコピーする必要がある場合のベスト プラクティスについてです。

例えば:

オブジェクトがあります{ name: 'Dodo', method: function () { console.log(this.name) }}

私はそれのコピーを作成する必要があります:

var obj = { name: 'Dodo', method: function () { console.log(this.name) } };
// what is better?
var copyUnderscore = _(obj).clone();
var copySimple = obj;

より良い方法は何ですか?ありがとう!

4

1 に答える 1

87

_.clone課題とは全く異なります。

_.clone新しいオブジェクトを作成し、各値を元のオブジェクトから新しいオブジェクトにコピーします。

割り当ては、既に存在するオブジェクトの変数を指すだけです。

あなたが子犬を飼っていたとします。彼をレックスと呼びましょう。

レックスについて誰かと話している場合は、彼をレックス、またはおそらく「犬」と呼びます。どちらも問題の動物への言及です。割り当ては、ペットにさまざまなフレーズを使用することに似ています。

rex = {
  type: 'Dog',
  age: '12 Weeks',
  name: "Rex",
  fixed: false,
  fix: function() {
    this.fixed = true;
    console.log(this.name + " Fixed.");
  }
};
theDog = rex;

// Note the use of `===`, which checks for object identity.
// Assignment (as above) is the whole point of `===`
if (theDog === rex) {
   alert("The Dog is the Same as Rex");
}

どちらかを変更すると、両方の参照が変更されます。したがって、Rex を「修正」するとします。

rex = {
  type: 'Dog',
  age: '12 Weeks',
  name: "Rex",
  fixed: false,
  fix: function() {
    this.fixed = true;
    console.log(this.name + " Fixed.");
  }
};
theDog = rex;
rex.fix();

alert("The Dog is " + (theDog.fixed ? "" : "not ") + "fixed");
alert("Rex is " + (rex.fixed ? "" : "not ") + "fixed");

theDogも固定されています。

ここで、Rex のクローンを作成したとします。(議論のために、彼はまだ修正されていないふりをしましょう)。

rex = {
  type: 'Dog',
  age: '12 Weeks',
  name: "Rex",
  fixed: false,
  fix: function() {
    this.fixed = true;
    console.log(this.name + " Fixed.");
  }
};
theDog = rex;
otherDog = _.clone(rex);

console.log(theDog);
console.log(rex);
console.log(otherDog);

var message = rex === theDog ? "Rex is the same as the dog" : "Rex and the dog are different";
message += "\n";
message += rex === otherDog ? "Rex is the same as the other dog" : "Rex is different from the other dog";
message += "\n";
message += rex.fixed ? "Rex is fixed" : "Rex is not fixed";
message += "\n";
message += otherDog.fixed ? "Other dog is fixed" : "Other dog is not fixed";

alert(message);

otherDog.fix();

message = rex.fixed ? "Rex is fixed" : "Rex is not fixed";
message += "\n";
message += otherDog.fixed ? "Other dog is fixed" : "Other dog is not fixed";
alert(message);
<script src="http://underscorejs.org/underscore-min.js"></script>

からの各値rexが にコピーされましたotherDog。奇跡的に「otherDog」が生後12週で生まれました。しかし、一方を修正しても他方は修正されません

rexとは同じ犬なのでtheDog、どちらも固定されていません。ただし固定ですotherDog 彼はクローンであり、同じ動物ではありません。

注意すべき微妙な点がいくつかあります。 _.clone深くコピーしません。これは、複製されたオブジェクトの値であるオブジェクトまたは配列が、代入によって新しいオブジェクトにコピーされることを意味します (意味の確認については、最初のスニペットを参照してください)。

これは、母親を表すオブジェクトでrexあるプロパティがあった場合、 と の間で共有されることを意味します。の母親への変更は、 に伝搬されます。これは実際の生活とそれほど違いはありません。生物学的母親は同一です。motherrexotherDogrexotherDog

編集

別の奇跡的なメモとして、固定された犬のクローンを作成すると、別の固定された犬が生成されます。ここで、生物学的な比喩が崩壊します。

もう一度編集 (2018 年 6 月)

この質問の読者にとって興味深いと思われる追加の ES6 機能が 2 つあります。

オブジェクトスプラット

_.clone以下は(メンバーのコピー) と同じです。

let x = {...rex};

Object.assign

次の例では、メンバーを既存のオブジェクトにコピーしてから、そのオブジェクトを返します。

let x = {}; let anotherReferenceToX = Object.assign(x, rex);

ボーナス!

lodash には実際ディープ クローン操作があることに注意してください。も使用できますfunction (x) { return JSON.parse(JSON.stringify(x)) }。しかし、それは循環参照を詰まらせますが、lodash はそうしません。

于 2013-06-06T12:21:28.057 に答える