我有一个物体x
。我想将其复制为对象y
,这样更改y
就不会修改x
。我意识到,复制从内置JavaScript对象派生的对象将导致额外的不需要的属性。这不是问题,因为我正在复制自己的文字构造对象之一。
如何正确克隆JavaScript对象?
在JavaScript中对任何对象执行此操作都不是简单或直接的。您将遇到错误地从对象的原型中获取应该留在原型中而不应复制到新实例的属性的问题。例如,如果您正在向中添加clone
方法Object.prototype
,如一些答案所示,则需要显式跳过该属性。但是,如果Object.prototype
您不知道其他附加方法或其他中间原型,该怎么办?在这种情况下,您将复制不应复制的属性,因此您需要使用方法来检测不可预见的非本地属性hasOwnProperty
。
除了不可枚举的属性外,当您尝试复制具有隐藏属性的对象时,还会遇到更棘手的问题。例如,prototype
是函数的隐藏属性。同样,对象的原型也具有属性__proto__
,该属性也被隐藏,并且不会通过在源对象的属性上进行迭代的for
/
in循环进行复制。我认为__proto__
可能是特定于Firefox的JavaScript解释器,在其他浏览器中可能有所不同,但是您会明白。并不是所有的东西都可以枚举。如果知道隐藏属性的名称,则可以复制它,但是我不知道有什么方法可以自动发现它。
寻求优雅解决方案的另一个障碍是正确设置原型继承的问题。如果您的源对象的原型是Object
,则只需创建一个新的通用对象即可{}
,但是如果源对象的原型是的某个后代Object
,则您将丢失该原型中使用hasOwnProperty
过滤器跳过的其他成员,或者是在原型中,但并非一开始就无法枚举。一种解决方案可能是调用源对象的constructor
属性以获取初始复制对象,然后在属性上进行复制,但是您仍然不会获得不可枚举的属性。例如,Date
对象将其数据存储为隐藏成员:
function clone(obj) {
if (null == obj || "object" != typeof obj) return obj;
var copy = obj.constructor();
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
}
return copy;
}
var d1 = new Date();
/* Executes function after 5 seconds. */
setTimeout(function(){
var d2 = clone(d1);
alert("d1 = " + d1.toString() + "\nd2 = " + d2.toString());
}, 5000);
的日期字符串d1
将比的日期字符串晚5秒d2
。使一个Date
与另一个相同的setTime
方法是调用方法,但这特定于Date
该类。我不认为该问题有防弹的一般解决方案,尽管我很高兴会犯错!
当我不得不实施一般深拷贝我最终通过假设我只需要复制一个普通的妥协Object
,Array
,Date
,String
,Number
,或Boolean
。后三种类型是不可变的,因此我可以执行浅表复制,而不必担心它会更改。我进一步假设该列表中包含的Object
或Array
也将是该6种简单类型之一的任何元素。这可以通过如下代码完成:
function clone(obj) {
var copy;
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
只要对象和数组中的数据形成树形结构,上述功能就可以对我提到的6个简单类型充分发挥作用。也就是说,对象中对同一数据的引用不止一个。例如:
// This would be cloneable:
var tree = {
"left" : { "left" : null, "right" : null, "data" : 3 },
"right" : null,
"data" : 8
};
// This would kind-of work, but you would get 2 copies of the
// inner node instead of 2 references to the same copy
var directedAcylicGraph = {
"left" : { "left" : null, "right" : null, "data" : 3 },
"data" : 8
};
directedAcyclicGraph["right"] = directedAcyclicGraph["left"];
// Cloning this would cause a stack overflow due to infinite recursion:
var cyclicGraph = {
"left" : { "left" : null, "right" : null, "data" : 3 },
"data" : 8
};
cyclicGraph["right"] = cyclicGraph;
它将无法处理任何JavaScript对象,但只要您不认为它会对您扔给它的任何东西起作用,它就可以满足许多目的。
问题内容: 我需要在我的没有超类的对象中实现一个深层克隆。 处理超类(即Object)引发的检查的最佳方法是什么? 一位同事建议我按以下方式处理: 对于我来说,这似乎是一个不错的解决方案,但我想将其扔给StackOverflow社区,以查看是否有我可以提供的其他见解。谢谢! 问题答案: 您绝对必须使用吗?大多数人都同意是坏的。 Josh Bloch谈设计-复制构造函数与克隆 如果您已经阅读了我书中
克隆当前板 采取行动 查看移动玩家是否处于检查中 如有,则不允许移动;否则,允许移动 我从这里获得关于如何克隆的提示: 现在,board对象由一个2D方形对象数组组成。每个方形对象都有一个piece字段,该字段要么为null(上面没有piece),要么引用一个piece对象(上面有一个piece)。board对象还有一个whiteKingSquare和一个blackKingSquare(都是方形对
问题内容: 我需要在我的没有超类的对象中实现一个深层克隆。 处理超类(即)引发的检查的最佳方法是什么? 一位同事建议我按以下方式处理: 对我来说,这似乎是一个不错的解决方案,但我想将其扔给StackOverflow社区,以查看是否有我可以提供的其他见解。 问题答案: 你绝对必须使用吗?大多数人都同意是坏的。 如果你已经阅读了我书中有关克隆的内容,尤其是你在两行之间阅读的话,你会知道我认为它clon
问题内容: 如果克隆数组,我将使用 我想知道如何在nodejs中克隆对象。 问题答案: 对于不需要压缩每一滴性能的实用程序和类,我经常作弊,只是使用JSON执行深层复制: 这不是唯一的答案,也不是最优雅的答案。所有其他答案都应考虑成为生产瓶颈。但是,这是一个快速而肮脏的解决方案,非常有效,并且在大多数情况下(我会克隆属性的简单哈希值)很有用。
我有下面的java代码,当我稍后尝试访问MiscDoc对象时,它似乎是空的。我找不到答案。NotesDocument上的clone()方法。 if语句只被访问一次 我该如何解决这个问题
本文向大家介绍如何实现对象克隆?相关面试题,主要包含被问及如何实现对象克隆?时的应答技巧和注意事项,需要的朋友参考一下 实现 Cloneable 接口并重写 Object 类中的 clone() 方法。 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。