栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何正确克隆JavaScript对象?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何正确克隆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();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 copyvar 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对象,但只要您不认为它会对您扔给它的任何东西起作用,它就可以满足许多目的。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/387894.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号