一、使用 JSON.parse
和 JSON.stringify
JSON.parse(JSON.stringify(obj))
缺点:
- 循环引用会报错。
- 性能较差。
- 会忽略 undefined,Date,RegExp,Error 等特殊对象。
二、使用递归
实现:
function isObj(obj) {
return typeof obj === 'object'
}
function deepClone(obj, hash = new WeakMap()) {
if (!isObj(obj) || obj === null || obj === undefined) return obj
let cloneObj
const Constructor = obj.constructor
switch (Constructor) {
case RegExp:
cloneObj = new Constructor(obj)
break
case Date:
cloneObj = new Constructor(obj.getTime())
break
case Array:
cloneObj = []
break
default:
if (hash.has(obj)) return hash.get(obj)
cloneObj = new Constructor()
hash.set(obj, cloneObj)
}
for (let key in obj) {
if (typeof obj[key] == 'function') {
cloneObj[key] = obj[key].bind(cloneObj)
} else {
cloneObj[key] = isObj(obj[key]) ? deepClone(obj[key], hash) : obj[key]
}
}
return cloneObj
}
参考实现:https://github.com/wengjq/Blog/issues/3
(function ($) {
'use strict';
var types = 'Array Object String Date RegExp Function Boolean Number Null Undefined'.split(' ');
function type () {
return Object.prototype.toString.call(this).slice(8, -1);
}
for (var i = types.length; i--;) {
$['is' + types[i]] = (function (self) {
return function (elem) {
return type.call(elem) === self;
};
})(types[i]);
}
return $;
})(window.$ || (window.$ = {}));//类型判断
function copy (obj,deep) {
if ($.isFunction(obj)) {
return new Function("return " + obj.toString())();
} else if (obj === null || (typeof obj !== "object")) {
return obj;
} else {
var name, target = $.isArray(obj) ? [] : {}, value;
for (name in obj) {
value = obj[name];
if (value === obj) {
continue;
}
if (deep) {
if ($.isArray(value) || $.isObject(value)) {
target[name] = copy(value,deep);
} else if ($.isFunction(value)) {
target[name] = new Function("return " + value.toString())();
} else {
target[name] = value;
}
} else {
target[name] = value;
}
}
return target;
}
}