什么是最有效的方式来克隆一个JavaScript对象?我已经看到obj = eval(uneval(o));被使用,但它是非标准的,仅支持Firefox.我做了事情,如obj = JSON.parse(JSON.stringify(o));但质疑效率。
当前回答
如果您正在使用它,UnderScore.js图书馆有一个克隆方法。
var newObject = _.clone(oldObject);
其他回答
对于未来的参考,目前的 ECMAScript 6 草案将 Object.assign 引入为克隆对象的一种方式。
var obj1 = { a: true, b: 1 };
var obj2 = Object.assign(obj1);
console.log(obj2); // { a: true, b: 1 }
在编写时,支持仅限于Firefox 34在浏览器中,所以它还不能在生产代码中使用(除非您正在编写Firefox扩展)。
对于未来的参考,可以使用此代码
第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}}
单线 ECMAScript 6 解决方案(特殊对象类型如 Date/Regex 未处理):
const clone = (o) => typeof o === 'object' && o!== null? // only clone objects (Array.isArray(o)? // if cloning an array o.map(e => clone(e)) : // clone each of its elements Object.keys(o).reduce( // otherwise reduce every key in the object (r, k) => (r[k] = clone(o[k]), r), {} // and save its cloned value
这是我创建的最快的方法,不使用原型,所以它将保持在新对象中拥有自己的所有权。
解决方案是对原件的顶级属性进行 iterate,创建两个副本,从原件中删除每个属性,然后重新设置原件并返回新副本,它只需要像顶级属性一样多次 iterate。
唯一的缺点是,原始对象必须配备其原创创建的名称空间,以便重新设置。
copyDeleteAndReset:function(namespace,strObjName){
var obj = namespace[strObjName],
objNew = {},objOrig = {};
for(i in obj){
if(obj.hasOwnProperty(i)){
objNew[i] = objOrig[i] = obj[i];
delete obj[i];
}
}
namespace[strObjName] = objOrig;
return objNew;
}
var namespace = {};
namespace.objOrig = {
'0':{
innerObj:{a:0,b:1,c:2}
}
}
var objNew = copyDeleteAndReset(namespace,'objOrig');
objNew['0'] = 'NEW VALUE';
console.log(objNew['0']) === 'NEW VALUE';
console.log(namespace.objOrig['0']) === innerObj:{a:0,b:1,c:2};
需要新的浏览器,但...
让我们扩展本地对象并获得一个真正的.extend();
Object.defineProperty(Object.prototype, 'extend', {
enumerable: false,
value: function(){
var that = this;
Array.prototype.slice.call(arguments).map(function(source){
var props = Object.getOwnPropertyNames(source),
i = 0, l = props.length,
prop;
for(; i < l; ++i){
prop = props[i];
if(that.hasOwnProperty(prop) && typeof(that[prop]) === 'object'){
that[prop] = that[prop].extend(source[prop]);
}else{
Object.defineProperty(that, prop, Object.getOwnPropertyDescriptor(source, prop));
}
}
});
return this;
}
});
只需在任何使用.extend() 对象的代码之前点击它。
例子:
var obj1 = {
node1: '1',
node2: '2',
node3: 3
};
var obj2 = {
node1: '4',
node2: 5,
node3: '6'
};
var obj3 = ({}).extend(obj1, obj2);
console.log(obj3);
// Object {node1: "4", node2: 5, node3: "6"}