1. 对象拷贝办法
1.1 JSON.parse
和JSON.stringify
办法
利用JSON.stringify
和JSON.parse
办法进行的是深拷贝,但无奈拷贝函数和undefined
,也无奈拷贝对象原型链上的属性和办法。
var obj = { a: 1, b: 2, c: { d: 4, // 在解析成 JSON 字符串时,undefined 不解析 e: undefined, // null 在 JSON 字符串中就是 null => "f": null f: null }, f: function () { console.log('function'); }};var newObj = JSON.parse(JSON.stringify(obj));console.log(newObj.c.d); // 4console.log(newObj.e); // undefinedconsole.log(newObj.f); // undefined
1.2 for-in
循环
利用for-in
循环进行的是浅拷贝,只拷贝根本类型的数据,对于援用类型的数据,只复制了指针。
var obj = { a: 1, b: { c: 3 }};var newObj = {};for (var key in obj) { newObj[key] = obj[key];}newObj.b.c = 4;console.log(obj.b.c); // 4console.log(newObj.b.c); // 4
1.3 Object.assign
办法
利用Object.assign
办法进行的是浅拷贝,拷贝源对象中的可枚举和自有属性。
var obj = { a: 1, b: { c: 3 }};var newObj = {};Object.assign(newObj, obj);newObj.b.c = 4;console.log(obj.b.c); // 4console.log(newObj.b.c); // 4
1.4 解构赋值
利用解构赋值办法进行的是浅拷贝。
var obj = { a: 1, b: { c: 1 }}var newObj = {...obj}newObj.b.c = 2console.log(obj.b.c) // 2console.log(newObj.b.c) // 2
2. 手写对象深拷贝办法
2.1 ES5 实现对象深拷贝
function deepClone (origin, target) { var _tar = target || {} for (var key in origin) { if (origin.hasOwnProperty(key)) { if (typeof origin[key] === 'object' && origin[key] !== null) { _tar[key] = Object.prototype.toString.call(origin[key]) === '[object Array]' ? [] : {}; deepClone(origin[key], _tar[key]); } else _tar[key] = origin[key]; } } return _tar}var obj = { a: 1, b: 2, c: { d: 4, e: 5 }, f: function () { console.log('function'); }};var newObj = {};deepClone(obj, newObj);console.log(newObj.c.d); // 4console.log(newObj.f); // undefined
2.2 ES6 实现对象深拷贝
function deepClone (origin) { if (origin == undefined || typeof origin !== 'object') return origin; if (origin instanceof Date) return new Date(origin); if (origin instanceof RegExp) return new RegExp(origin); const target = new origin.constructor(); for (let key in origin) { if (origin.hasOwnProperty(key)) { target[key] = deepClone(origin[key]); } } return target;}
可能实现对象深拷贝,但当呈现循环援用时会导致死循环。因而须要利用WeakMap
保留已进行过拷贝的对象,避免死循环。
function deepClone (origin, hashMap = new WeakMap()) { if (origin == undefined || typeof origin !== 'object') return origin; if (origin instanceof Date) return new Date(origin); if (origin instanceof RegExp) return new RegExp(origin); const hashVal = hashMap.get(origin); if (hashVal) return hashVal; const target = new origin.constructor(); hashMap.set(origin, target); for (let key in origin) { if (origin.hasOwnProperty(key)) { target[key] = deepClone(origin[key]); } } return target;}