什么是最有效的方式来克隆一个JavaScript对象?我已经看到obj = eval(uneval(o));被使用,但它是非标准的,仅支持Firefox.我做了事情,如obj = JSON.parse(JSON.stringify(o));但质疑效率。
当前回答
如果你发现自己做这种类型的事情是正常的(例如,创建 undo redo 功能 ) 它可能值得看看 Immutable.js
const map1 = Immutable.fromJS( { a: 1, b: 2, c: { d: 3 } } );
const map2 = map1.setIn( [ 'c', 'd' ], 50 );
console.log( `${ map1.getIn( [ 'c', 'd' ] ) } vs ${ map2.getIn( [ 'c', 'd' ] ) }` ); // "3 vs 50"
https://codepen.io/anon/pen/OBpqNE?编辑器=1111
其他回答
因为回归只是太昂贵的JavaScript,我发现的大多数答案是使用回归,而JSON方法将错过非JSON转换部分(功能等)。所以我做了一些研究,并发现这个拖拉机技术避免它。
/*
* Trampoline to avoid recursion in JavaScript, see:
* https://www.integralist.co.uk/posts/functional-recursive-javascript-programming/
*/
function trampoline() {
var func = arguments[0];
var args = [];
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
var currentBatch = func.apply(this, args);
var nextBatch = [];
while (currentBatch && currentBatch.length > 0) {
currentBatch.forEach(function(eachFunc) {
var ret = eachFunc();
if (ret && ret.length > 0) {
nextBatch = nextBatch.concat(ret);
}
});
currentBatch = nextBatch;
nextBatch = [];
}
};
/*
* Deep clone an object using the trampoline technique.
*
* @param target {Object} Object to clone
* @return {Object} Cloned object.
*/
function clone(target) {
if (typeof target !== 'object') {
return target;
}
if (target == null || Object.keys(target).length == 0) {
return target;
}
function _clone(b, a) {
var nextBatch = [];
for (var key in b) {
if (typeof b[key] === 'object' && b[key] !== null) {
if (b[key] instanceof Array) {
a[key] = [];
}
else {
a[key] = {};
}
nextBatch.push(_clone.bind(null, b[key], a[key]));
}
else {
a[key] = b[key];
}
}
return nextBatch;
};
var ret = target instanceof Array ? [] : {};
(trampoline.bind(null, _clone))(target, ret);
return ret;
};
我迟到回答这个问题,但我有另一种方式来克隆对象:
function cloneObject(obj) {
if (obj === null || typeof(obj) !== 'object')
return obj;
var temp = obj.constructor(); // changed
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
obj['isActiveClone'] = null;
temp[key] = cloneObject(obj[key]);
delete obj['isActiveClone'];
}
}
return temp;
}
var b = cloneObject({"a":1,"b":2}); // calling
更快、更快的是:
var a = {"a":1,"b":2};
var b = JSON.parse(JSON.stringify(a));
和
var a = {"a":1,"b":2};
// Deep copy
var newObject = jQuery.extend(true, {}, a);
我已经标记了代码,你可以在这里测试结果:
和分享结果: 参考: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
在 JavaScript 中,您可以写下您的 deepCopy 方法如:
function deepCopy(src) {
let target = Array.isArray(src) ? [] : {};
for (let prop in src) {
let value = src[prop];
if(value && typeof value === 'object') {
target[prop] = deepCopy(value);
} else {
target[prop] = value;
}
}
return target;
}
function clone(obj)
{ var clone = {};
clone.prototype = obj.prototype;
for (property in obj) clone[property] = obj[property];
return clone;
}
使用 Object.create() 获取原型和支持的例子,并使用 for() 圈获取可列的密钥:
function cloneObject(source) {
var key,value;
var clone = Object.create(source);
for (key in source) {
if (source.hasOwnProperty(key) === true) {
value = source[key];
if (value!==null && typeof value==="object") {
clone[key] = cloneObject(value);
} else {
clone[key] = value;
}
}
}
return clone;
}