什么是最有效的方式来克隆一个JavaScript对象?我已经看到obj = eval(uneval(o));被使用,但它是非标准的,仅支持Firefox.我做了事情,如obj = JSON.parse(JSON.stringify(o));但质疑效率。
当前回答
function clone(obj) {
var copy;
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
使用下列方法而不是 JSON.parse(JSON.stringify(obj)) 因为它比下列方法慢。
我如何正确地克隆一个JavaScript对象?
其他回答
希望这能帮助。
function deepClone(obj) {
/*
* Duplicates an object
*/
var ret = null;
if (obj !== Object(obj)) { // primitive types
return obj;
}
if (obj instanceof String || obj instanceof Number || obj instanceof Boolean) { // string objecs
ret = obj; // for ex: obj = new String("Spidergap")
} else if (obj instanceof Date) { // date
ret = new obj.constructor();
} else
ret = Object.create(obj.constructor.prototype);
var prop = null;
var allProps = Object.getOwnPropertyNames(obj); //gets non enumerables also
var props = {};
for (var i in allProps) {
prop = allProps[i];
props[prop] = false;
}
for (i in obj) {
props[i] = i;
}
//now props contain both enums and non enums
var propDescriptor = null;
var newPropVal = null; // value of the property in new object
for (i in props) {
prop = obj[i];
propDescriptor = Object.getOwnPropertyDescriptor(obj, i);
if (Array.isArray(prop)) { //not backward compatible
prop = prop.slice(); // to copy the array
} else
if (prop instanceof Date == true) {
prop = new prop.constructor();
} else
if (prop instanceof Object == true) {
if (prop instanceof Function == true) { // function
if (!Function.prototype.clone) {
Function.prototype.clone = function() {
var that = this;
var temp = function tmp() {
return that.apply(this, arguments);
};
for (var ky in this) {
temp[ky] = this[ky];
}
return temp;
}
}
prop = prop.clone();
} else // normal object
{
prop = deepClone(prop);
}
}
newPropVal = {
value: prop
};
if (propDescriptor) {
/*
* If property descriptors are there, they must be copied
*/
newPropVal.enumerable = propDescriptor.enumerable;
newPropVal.writable = propDescriptor.writable;
}
if (!ret.hasOwnProperty(i)) // when String or other predefined objects
Object.defineProperty(ret, i, newPropVal); // non enumerable
}
return ret;
}
HTTPS://github.com/jinujd/Javascript-Deep-Clone
下面是我如何深度克隆一个与ES2015默认值和扩展操作器的对象
const makeDeepCopy = (obj, copy = {}) => {
for (let item in obj) {
if (typeof obj[item] === 'object') {
makeDeepCopy(obj[item], copy)
}
if (obj.hasOwnProperty(item)) {
copy = {
...obj
}
}
}
return copy
}
const testObj = {“类型”:“对象”,“属性”: {“用户Id”: {“类型”:“string”,“机会”:“指南” },“emailAddr”: {“类型”:“string”,“机会”: {“电子邮件”: {“域名”:“fake.com” },“模式”:“+@fake.com” },“需要”: {“用户Id”,“emailAddr” } } const makeDeepCopy = (ob)
单线 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
只是因为我没有看到AngularJS提到并认为人们可能想知道......
angular.copy 还提供深复制对象和序列的方法。
克罗克福德建议(我更喜欢)使用此功能:
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var newObject = object(oldObject);
它是干净的,工作如预期,你不需要图书馆。
编辑:
这是一个对 Object.create 的聚合物,所以你也可以使用它。
var newObject = Object.create(oldObject);
注意: 如果你使用其中的一些,你可能有问题与某些 iteration谁使用 hasOwnProperty. 因为,创建创造新的空的对象,继承旧的对象. 但它仍然有用和实用的克隆对象。
例如,如果 oldObject.a = 5;
newObject.a; // is 5
但:
oldObject.hasOwnProperty(a); // is true
newObject.hasOwnProperty(a); // is false