下划线clone()和简单'='之间有什么区别?

Kos*_*ika 23 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;
Run Code Online (Sandbox Code Playgroud)

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

Cri*_*ole 84

_.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");
}
Run Code Online (Sandbox Code Playgroud)

当您更改某个内容时,它会针对两个引用进行更改.所以假设你"修复"雷克斯:

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");
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)
<script src="http://underscorejs.org/underscore-min.js"></script>
Run Code Online (Sandbox Code Playgroud)

每个值rex都已复制到otherDog.奇迹般地,"otherDog"出生于12周岁.但修复一个不会修复另一个.

现在既然rextheDog是同一只狗,也没有固定.但是,otherDog 固定的.他是一个克隆人,而不是同一个动物.

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

这意味着如果rex有一个属性mother代表他的母亲,它将在rex和之间共享otherDog.对rex母亲的任何改变都会传播到otherDog.这与现实生活没有什么不同; 亲生母亲是同一个.

编辑

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

再次编辑(2018年6月)

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

对象Splat

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

let x = {...rex};

Object.assign

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

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

奖金!

值得注意的是,lodash实际上一个深度克隆操作.你也可以使用function (x) { return JSON.parse(JSON.stringify(x)) }.但是这会引起循环引用,并且lodash不会.

  • 引用和指针很棘手.不要气馁,只要在现实生活中找到类比,直到你得到它......它可能需要一段时间,但它非常重要.认识到你并不理解差异的好工作. (9认同)
  • 不要忘记[`underscore.clone(obj)`](http://underscorejs.org/#clone)只给你一个浅拷贝 (6认同)