下划线克隆()与简单' ='之间的区别是什么?

时间:2013-06-06 12:18:38

标签: javascript object underscore.js

当你需要在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;

更好的方法是什么?谢谢!

1 个答案:

答案 0 :(得分:83)

_.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周岁。但修复一个修复另一个。

由于rextheDog是同一只狗,因此两者都没有固定。但是,otherDog 已修复。他是一个克隆人,而不是同一种动物。

要注意一些细微之处。 _.clone不会深深复制。这意味着克隆对象中任何值的任何对象或数组都会被赋值复制到新对象(请参阅第一个片段以查看其含义)。

这意味着如果rex的属性mother是代表其母亲的对象,则会在rexotherDog之间共享。对rex母亲的任何更改都会传播到otherDog。这与现实生活没有什么不同;亲生母亲是同一个。

修改

作为另一个神奇的笔记:克隆固定的狗产生另一个固定的狗。这就是生物隐喻崩溃的地方。

再次编辑(2018年6月)

这个问题的读者可能会对另外两个ES6功能感兴趣:

Object Splat

以下内容与_.clone(复制成员)相同:

let x = {...rex};

Object.assign

以下将成员复制到现有对象,然后返回该对象:

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

<强>奖金!

值得注意的是lodash actually has a deep clone operation。您也可以使用function (x) { return JSON.parse(JSON.stringify(x)) }。但这会引起循环引用,而lodash则不会。