web-dev-qa-db-ja.com

アンダースコアclone()と単純な「=」の違いは何ですか?

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;

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

23
Kosmetika

__.clone_は、割り当てとはまったく異なります。

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

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

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

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

_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");
}_

1つについて何かを変更すると、両方の参照についても変更されます。レックスを「修正」するとします。

_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 = {
  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週齢で生まれました。ただし、一方を修正すると他方は修正されません

rextheDogは同じ犬なので、どちらも修正されていません。ただし、otherDogisは修正されています。彼はクローンであり、同じ動物ではありません。

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

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

[〜#〜] edit [〜#〜]

別の奇跡的なメモとして:固定犬のクローンを作成すると、別の固定犬が作成されます。これは、生物学的メタファーが壊れる場所です。

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

この質問の読者が興味を持つ可能性のある2つの追加のES6機能があります。

オブジェクトスプラット

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

_let x = {...rex};_

Object.assign

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

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

ボーナス!

lodashは実際にはに深いクローン操作がある であることに注意する価値があります。 function (x) { return JSON.parse(JSON.stringify(x)) }を使用することもできます。しかし、それは循環参照で窒息し、lodashはそうではありません。

83
Crisfole