如何在不使用 JSON.stringify 或 JSON.parse 的情况下在 javascript 中克隆数组? [复制]

Posted

技术标签:

【中文标题】如何在不使用 JSON.stringify 或 JSON.parse 的情况下在 javascript 中克隆数组? [复制]【英文标题】:How to clone an array in javascript without using JSON.stringify or JSON.parse? [duplicate] 【发布时间】:2014-11-05 21:10:30 【问题描述】:

我有一个数组示例 fruit 。我想将它复制为数组fruits2,而不保留引用。

在下面的示例中,引用被保留,所以 fruits 被修改。


var fruit = function (name)
    this.name = name;

var fruits = [];
fruits.push(new fruit('apple'));
fruits.push(new fruit('banana'));
fruits.push(new fruit('orange'));

var fruits2 = fruits;
fruits2.length = 0;
console.log(fruits);

http://jsfiddle.net/vkdqur82/


使用 JSON.stringify 和 JSON.parse 可以解决问题,但 fruits2 中的对象不再是 fruit 类型,而是一般类型 object

var temp = JSON.stringify(fruits);
var fruits2 = JSON.parse(temp);

我想知道另一种方法可以保留fruit 的内部对象。

【问题讨论】:

使用 jquery:jsfiddle.net/vkdqur82/4 相关使用jquery:***.com/questions/16512773/… oranlooney.com/deep-copy-javascript 这是一种使用 Object.setPrototypeOf() 创建新对象的方法,不使用 JSON,不重新调用构造函数,但仍保留自定义构造函数和继承的方法,而不将所有内容提升为拥有属性或迭代:jsfiddle.net/rndme/x3tz5kzc(仅适用于较新的浏览器,但这是最好的解决方案) @dandavis 感谢分享,我只是想知道跨浏览器的兼容性,因为 Object.setPrototypeOf() 是 Harmony (ECMAScript 6) 【参考方案1】:

使用slicevar fruits2 = fruits.slice(); 应该这样做。

您的jsFiddle,已修改

另见:MDN

**编辑。我有点懒,让我们更正我的答案以弥补这一点。

对于仅值 sliceArray 来说是完美的。对于对象或数组的Array 或值/对象/数组的混合,要克隆的ArrayArrayObject 元素也需要克隆。否则,它们将是对原始数组或对象的引用(因此:不是副本),并且 [其中一个数组或对象的引用] 的更改将反映在包含对它的引用的所有“克隆”中。

要克隆数组/对象/混合值的Array Array.map 是您的朋友。有几种方法可以考虑:

    使用旧数据创建新实例var fruits1 = fruits.map(function(v) return new Fruit(v.name);); 使用 JSONvar fruits2 = fruits.map(function(v) return JSON.parse(JSON.stringify(v));); 创建和使用一些克隆方法var fruits3 = fruits.map(function(v) return cloneObj(v););

在情况 3 中,克隆方法可能如下所示:

function cloneObj(obj) 
    function clone(o, curr) 
        for (var l in o)
            if (o[l] instanceof Object) 
                curr[l] = cloneObj(o[l]);
             else 
                curr[l] = o[l];
            
        
        return curr;
    
    
    return obj instanceof Array 
             ? obj.slice().map( function (v)  return cloneObj(v);  )
             : obj instanceof Object 
               ? clone(obj, )
               : obj;

使用此cloneObj 方法,Array.map 已过时。 你也可以使用var fruitsx = cloneObj(fruits);

修改了上面链接中的 jsFiddle 来演示这些方法。

对于Array.map,请再次查看MDN

【讨论】:

或者简单地说,fruits.slice()(没有参数)。 是的,零只是习惯,删除它。 根本不克隆对象,它只是创建一个相同对象的新列表。如果您解析(stringify()),则更改新对象不会影响旧对象。按照编码,对旧的或新的更改将出现在另一个中。我并不是说这会破坏交易,但它与 OP 提到的基于 JSON 的克隆有很大不同 @dandavis iwhat about using jquery for deepcopy... smt like... var fruis2 = $.extend(true, [], fruits) ?? 对不起我的懒惰,我希望我的更正答案能让事情更清楚。 @GibboK:$.extend 将在Array 中保留对对象的引用,换句话说,不会真正复制它们。【参考方案2】:

slice 可以解决问题。

您也可以使用.map,但.slice 通常更快。

var copy = fruits.map(function(item) return item);

希望对你有帮助

【讨论】:

【参考方案3】:

您可以声明一个新数组并使用 concat 方法,以便将数组中的所有值连接到新数组。像这样的:

var x = ["a","b"];
var a = [];
a = a.concat(x);
console.log(a);

我编辑了我糟糕的答案。

最好的问候。

【讨论】:

这看起来不像是一个答案。应该是评论。 对不起,我是用手机接的。这是我第一次使用它。让我们看看我是否可以删除它。谢谢。

以上是关于如何在不使用 JSON.stringify 或 JSON.parse 的情况下在 javascript 中克隆数组? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

JS JSON格式化打印:JSON.stringify方法

如何提升JSON.stringify()的性能?

如何快速提升 JSON.stringify() 的性能?

如何在 Swift 中将 JSON 转换为数据类型?

JSON.stringify()

JSON.stringify()