如何在不使用 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】:使用slice
:var fruits2 = fruits.slice();
应该这样做。
您的jsFiddle,已修改
另见:MDN
**编辑。我有点懒,让我们更正我的答案以弥补这一点。
对于仅值 slice
的 Array
来说是完美的。对于对象或数组的Array
或值/对象/数组的混合,要克隆的Array
的Array
和Object
元素也需要克隆。否则,它们将是对原始数组或对象的引用(因此:不是副本),并且 [其中一个数组或对象的引用] 的更改将反映在包含对它的引用的所有“克隆”中。
要克隆数组/对象/混合值的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 中克隆数组? [复制]的主要内容,如果未能解决你的问题,请参考以下文章