什么是最有效的方式来克隆一个JavaScript对象?我已经看到obj = eval(uneval(o));被使用,但它是非标准的,仅支持Firefox.我做了事情,如obj = JSON.parse(JSON.stringify(o));但质疑效率。
当前回答
只是因为我没有看到AngularJS提到并认为人们可能想知道......
angular.copy 还提供深复制对象和序列的方法。
其他回答
以下是 ConroyP 上面的答案的版本,即使制造商需要参数:
//If Object.create isn't already defined, we just do the simple shim,
//without the second argument, since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
object_create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}
function deepCopy(obj) {
if(obj == null || typeof(obj) !== 'object'){
return obj;
}
//make sure the returned object has the same prototype as the original
var ret = object_create(obj.constructor.prototype);
for(var key in obj){
ret[key] = deepCopy(obj[key]);
}
return ret;
}
此功能也在我的 simpleoo 图书馆中可用。
编辑:
下面是一个更坚实的版本(感谢Justin McCandless,现在支持自行车参考):
/**
* Deep copy an object (make copies of all its object properties, sub-properties, etc.)
* An improved version of http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
* that doesn't break if the constructor has required parameters
*
* It also borrows some code from http://stackoverflow.com/a/11621004/560114
*/
function deepCopy(src, /* INTERNAL */ _visited, _copiesVisited) {
if(src === null || typeof(src) !== 'object'){
return src;
}
//Honor native/custom clone methods
if(typeof src.clone == 'function'){
return src.clone(true);
}
//Special cases:
//Date
if(src instanceof Date){
return new Date(src.getTime());
}
//RegExp
if(src instanceof RegExp){
return new RegExp(src);
}
//DOM Element
if(src.nodeType && typeof src.cloneNode == 'function'){
return src.cloneNode(true);
}
// Initialize the visited objects arrays if needed.
// This is used to detect cyclic references.
if (_visited === undefined){
_visited = [];
_copiesVisited = [];
}
// Check if this object has already been visited
var i, len = _visited.length;
for (i = 0; i < len; i++) {
// If so, get the copy we already made
if (src === _visited[i]) {
return _copiesVisited[i];
}
}
//Array
if (Object.prototype.toString.call(src) == '[object Array]') {
//[].slice() by itself would soft clone
var ret = src.slice();
//add it to the visited array
_visited.push(src);
_copiesVisited.push(ret);
var i = ret.length;
while (i--) {
ret[i] = deepCopy(ret[i], _visited, _copiesVisited);
}
return ret;
}
//If we've reached here, we have a regular object
//make sure the returned object has the same prototype as the original
var proto = (Object.getPrototypeOf ? Object.getPrototypeOf(src): src.__proto__);
if (!proto) {
proto = src.constructor.prototype; //this line would probably only be reached by very old browsers
}
var dest = object_create(proto);
//add this object to the visited array
_visited.push(src);
_copiesVisited.push(dest);
for (var key in src) {
//Note: this does NOT preserve ES5 property attributes like 'writable', 'enumerable', etc.
//For an example of how this could be modified to do so, see the singleMixin() function
dest[key] = deepCopy(src[key], _visited, _copiesVisited);
}
return dest;
}
//If Object.create isn't already defined, we just do the simple shim,
//without the second argument, since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
object_create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}
什么是无与伦比的对象克隆,由一个承诺完成?
async function clone(thingy /**/)
{
if(thingy instanceof Promise)
{
throw Error("This function cannot clone Promises.");
}
return thingy;
}
Lodash 有一个可爱的 _.cloneDeep(值) 方法:
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false
使用 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;
}
Lodash 有一个功能,以便你这样做。
var foo = {a: 'a', b: {c:'d', e: {f: 'g'}}};
var bar = _.cloneDeep(foo);
// bar = {a: 'a', b: {c:'d', e: {f: 'g'}}}
阅读这里的DOC。