如何使用underscore克隆一个对象数组?
如何使用underscore克隆一个对象数组?
使用精简的语言将下面的内容翻译成中文:
#!/usr/bin/env node var _ = require('underscore'); var a = [{f: 1}, {f:5}, {f:10}]; var b = _.clone(a); b[1].f = 55; console.log(JSON.stringify(a));
运行结果是:
[{"f":1},{"f":55},{"f":10}]
克隆似乎不起作用!
所以我阅读了文档,找到了这个:
http://underscorejs.org/#clone
创建一个浅复制的对象副本。任何嵌套的对象或数组将被引用复制,而不是复制副本。
所以 _.clone
是相当无用的。有没有办法真正复制对象数组?
如何使用underscore克隆一个对象数组?
在Github上的一个问题中,有人提出了另一种解决方案,它适用于任何层级的嵌套数据,而且不需要使用underscore:
JSON.parse(JSON.stringify(obj))
这种方法在对象没有循环引用的情况下是有效的,否则JSON.stringify
会抛出一个错误。在原始问题中并不存在循环引用的情况,但这仍然是一个有趣的情况。
另外值得注意的是,这种解决方案只适用于具有简单类型的对象。例如,如果对象中有Date
或Regex
类型的实例,它们将被序列化为字符串。这不是什么大问题,但如果你在使用这个方法并且期望Date
实例时,你需要处理它们。
如果你认为有人可能会尝试将undefined
传递给这个方法,你应该使用JSON.parse(JSON.stringify(obj) || null)
,否则它会抛出一个错误。
此外,这种方法将完全丢弃function
。
问题的出现原因是使用underscore的clone方法在克隆数组对象时,并不能克隆嵌套的对象。解决方法是通过在map调用中显式克隆每个对象来强制克隆嵌套对象。具体实现如下:
var _ = require('underscore'); var a = [{f: 1}, {f:5}, {f:10}]; var b = _.map(a, _.clone); // <---- b[1].f = 55; console.log(JSON.stringify(a));
输出结果为:
[{"f":1},{"f":5},{"f":10}]
这样,a数组保持不变,可以对b数组进行任意编辑。
需要注意的是,这种方法只适用于两层嵌套,对于嵌套更深的数组或对象无效。
此外,underscore也无法正确克隆RegExp或Date类型的值。