什么是最有效的方式来克隆一个JavaScript对象?我已经看到obj = eval(uneval(o));被使用,但它是非标准的,仅支持Firefox.我做了事情,如obj = JSON.parse(JSON.stringify(o));但质疑效率。
当前回答
对于未来的参考,可以使用此代码
第6章:
_clone: function(obj){
let newObj = {};
for(let i in obj){
if(typeof(obj[i]) === 'object' && Object.keys(obj[i]).length){
newObj[i] = clone(obj[i]);
} else{
newObj[i] = obj[i];
}
}
return Object.assign({},newObj);
}
第5章:
function clone(obj){
let newObj = {};
for(let i in obj){
if(typeof(obj[i]) === 'object' && Object.keys(obj[i]).length){
newObj[i] = clone(obj[i]);
} else{
newObj[i] = obj[i];
}
}
return Object.assign({},newObj);
) )
E.G
var obj ={a:{b:1,c:3},d:4,e:{f:6}}
var xc = clone(obj);
console.log(obj); //{a:{b:1,c:3},d:4,e:{f:6}}
console.log(xc); //{a:{b:1,c:3},d:4,e:{f:6}}
xc.a.b = 90;
console.log(obj); //{a:{b:1,c:3},d:4,e:{f:6}}
console.log(xc); //{a:{b:90,c:3},d:4,e:{f:6}}
其他回答
Object.assign({},sourceObj)只有在其属性没有参考类型密钥时才会克隆对象。
obj={a:"lol",b:["yes","no","maybe"]}
clonedObj = Object.assign({},obj);
clonedObj.b.push("skip")// changes will reflected to the actual obj as well because of its reference type.
obj.b //will also console => yes,no,maybe,skip
因此,对于深度克隆,不可能以这种方式实现。
最有效的解决方案是
var obj = Json.stringify(yourSourceObj)
var cloned = Json.parse(obj);
如何将对象的关键与其价值相结合?
function deepClone(o) {
var keys = Object.keys(o);
var values = Object.values(o);
var clone = {};
keys.forEach(function(key, i) {
clone[key] = typeof values[i] == 'object' ? Object.create(values[i]) : values[i];
});
return clone;
}
注意: 这种方法不一定会做更深的复制,但它只会用一个内部对象的深度复制,这意味着当你给出像 {a: {b: {c: null}}} 这样的东西时,它只会克隆直接在它们内部的对象,所以 deepClone(a.b.c)技术上是对 a.b.c 的参考,而 deepClone(a.b)则是克隆,而不是参考。
我知道这是一个古老的帖子,但我以为这可能有助于下一个人,谁在跳动。
只要你不分配一个对象到任何东西,它保留没有参考在记忆中,所以要创建一个对象,你想在其他对象中分享,你将不得不创建一个工厂如下:
var a = function(){
return {
father:'zacharias'
};
},
b = a(),
c = a();
c.father = 'johndoe';
alert(b.father);
这通常不是最有效的解决方案,但它是我需要的。
function clone(obj, clones) {
// Makes a deep copy of 'obj'. Handles cyclic structures by
// tracking cloned obj's in the 'clones' parameter. Functions
// are included, but not cloned. Functions members are cloned.
var new_obj,
already_cloned,
t = typeof obj,
i = 0,
l,
pair;
clones = clones || [];
if (obj === null) {
return obj;
}
if (t === "object" || t === "function") {
// check to see if we've already cloned obj
for (i = 0, l = clones.length; i < l; i++) {
pair = clones[i];
if (pair[0] === obj) {
already_cloned = pair[1];
break;
}
}
if (already_cloned) {
return already_cloned;
} else {
if (t === "object") { // create new object
new_obj = new obj.constructor();
} else { // Just use functions as is
new_obj = obj;
}
clones.push([obj, new_obj]); // keep track of objects we've cloned
for (key in obj) { // clone object members
if (obj.hasOwnProperty(key)) {
new_obj[key] = clone(obj[key], clones);
}
}
}
}
return new_obj || obj;
}
自行车测试...
a = []
a.push("b", "c", a)
aa = clone(a)
aa === a //=> false
aa[2] === a //=> false
aa[2] === a[2] //=> false
aa[2] === aa //=> true
功能测试...
f = new Function
f.a = a
ff = clone(f)
ff === f //=> true
ff.a === a //=> false
代码:
// extends 'from' object with members from 'to'. If 'to' is null, a deep clone of 'from' is returned
function extend(from, to)
{
if (from == null || typeof from != "object") return from;
if (from.constructor != Object && from.constructor != Array) return from;
if (from.constructor == Date || from.constructor == RegExp || from.constructor == Function ||
from.constructor == String || from.constructor == Number || from.constructor == Boolean)
return new from.constructor(from);
to = to || new from.constructor();
for (var name in from)
{
to[name] = typeof to[name] == "undefined" ? extend(from[name], null) : to[name];
}
return to;
}
测试:
var obj =
{
date: new Date(),
func: function(q) { return 1 + q; },
num: 123,
text: "asdasd",
array: [1, "asd"],
regex: new RegExp(/aaa/i),
subobj:
{
num: 234,
text: "asdsaD"
}
}
var clone = extend(obj);
推荐文章
- 转换php数组到Javascript
- 如何跳转到浏览器页面的顶部
- 在电子邮件消息中是否支持JavaScript ?
- 如何在JavaScript中指定Math.log()的基?
- 多重左赋值JavaScript
- 如何在单个测试基础上更改模拟实现?
- VueJS有条件地为元素添加属性
- Uncaught TypeError:(中间值)(…)不是一个函数
- 如何设置URL查询参数在Vue与Vue路由器
- 无法读取属性“addEventListener”为空
- 如何防止moment.js从webpack加载地区?
- getMonth在javascript中给出前一个月
- 如何在禁用按钮上启用引导工具提示?
- Node.js全局变量
- 在前一个函数完成后调用另一个函数