一、使用 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 objlet cloneObjconst Constructor = obj.constructorswitch (Constructor) {case RegExp:cloneObj = new Constructor(obj)breakcase Date:cloneObj = new Constructor(obj.getTime())breakcase Array:cloneObj = []breakdefault: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;}}
