2011-11-21 113 views
30

如何在JavaScript中克隆/复制地图?克隆/复制Javascript地图变量

我知道如何克隆一个数组,但是如何克隆/复制一张地图?

var myArray = new Array(1, 2, 3); 
var copy = myArray.slice(); 
// now I can change myArray[0] = 5; & it wont affect copy array 

// Can I just do the same for map? 
var myMap = new ?? // in javascript is it called a map? 
var myMap = {"1": 1, "2", 2}; 
var copy = myMap.slice(); 
+0

在JavaScript中,地图被称为对象。 – slebetman

+0

有这么多重复的这个问题,我甚至不知道从哪里开始! – Stefano

+7

在2015年的JavaScript中,有一个真正的Map对象。 –

回答

10

一个简单的方法是将源地图的每个属性复制到目标地图:

var newMap = {}; 
for (var i in myMap) 
newMap[i] = myMap[i]; 
+2

这只是一个浅拷贝...如果myMap [i]本身就是一张地图呢? – Stefano

+0

Stefano,你可以做到这一点,如果你想(检查是否是一个typeof对象,然后执行它的属性的副本...可能是通过递归相同的函数),但请记住,现在你必须关心它们作为祖先元素的可能性,这会使你陷入无限循环。如果你真的想要一个深层的副本,你可能想看看这样做的图书馆。 – rob

+1

我知道,但我认为你应该先在你的答案中写下这一点;-) – Stefano

2

没有内置的克隆/复制。您可以将自己的方法写入浅拷贝或深拷贝:

function shallowCopy(obj) { 
    var result = {}; 
    for (var i in obj) { 
     result[i] = obj[i]; 
    } 
    return result; 
} 

function deepCopy(obj) { 
    var result = {}; 
    for (var i in obj) { 
     // recursion here, though you'll need some non-trivial logic 
     // to avoid getting into an endless loop. 
    } 
    return result; 
} 

Javascript中的所有对象都是动态的,并且可以分配新的属性。你引用它的“地图”实际上只是一个空的对象。一个数组是也是的一个对象,使用方法如slice和属性如length

+0

不明白你写的2个函数有什么不同之处! –

+0

@HananAYousef区别未实现;在深层复制中,您必须递归(为每个子节点调用deepCopy),但由于子节点可能包含对父节点的引用(例如,window.window2 = window),因此无法深入复制这些引用而无法进入无限循环。 – Nicole

2

没有什么内置

要么使用一个行之有效的递归特性复印机或者性能ISN是一个问题,串行化为JSON并再次解析为新对象。

6

JQuery有一个方法来扩展一个对象(合并两个对象),但是这个方法也可以用来通过提供一个空对象来克隆一个对象。

// Shallow copy 
var newObject = jQuery.extend({}, oldObject); 

// Deep copy 
var newObject = jQuery.extend(true, {}, oldObject); 

更多信息可在jQuery documentation中找到。这里

var newMap = new Map(existingMap) 

文档:

111

在JavaScript中引入地图这是很简单的考虑构造函数接受一个可迭代https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

+9

这是今天正确的答案。 –

+0

上面的小问题:像这样克隆地图,会调用Map.prototype.entries和Map.prototype.set。这意味着:如果您编写扩展Map的类并覆盖这两种方法中的任何一种,那么如果扩展方法依赖super所不具备的属性,那么只需编写'new ExtendedMap(extendedMapObj)'就不会起作用。 –

+2

另一个需要注意的是,如果映射值是引用类型(如数组),看起来好像不是递归深度复制的,而是浅拷贝的。 – ossek

1

我注意到,地图应该需要特殊的处理,因此与所有建议此线程的代码将为:

function deepClone(obj) { 
    if(!obj || true == obj) //this also handles boolean as true and false 
     return obj; 
    var objType = typeof(obj); 
    if("number" == objType || "string" == objType) // add your immutables here 
     return obj; 
    var result = Array.isArray(obj) ? [] : !obj.constructor ? {} : new obj.constructor(); 
    if(obj instanceof Map) 
     for(var key of obj.keys()) 
      result.set(key, deepClone(obj.get(key))); 
    for(var key in obj) 
     if(obj.hasOwnProperty(key)) 
      result[key] = deepClone(obj[ key ]); 
    return result; 
} 
0

克隆地图非常简单,因为您所谈论的是强制一个物体。有一个在ES6一个Map,你应该看看,但复制的对象,只要使用Object.assign()

let map = {"a": 1, "b": 2} 
let copy = Object.assign({}, map); 

您还可以使用cloneDeep()从Lodash

let copy = cloneDeep(map);