一、须要知识点回顾
根本类型(值类型)和援用类型
(根本类型)值类型:Number,Boolean,String,undefined,null
援用类型:object,Arrary
二、根本类型和援用类型复制的区别
值类型:对值类型的复制操作,仅仅是对值的进行一份拷贝,复制与被复制的会指向两份不同的数据。
援用类型:援用类型复制的是地址。所以最初会发现,复制与被复制的最终会指向同一份数据。
例子:
// 根本类型var a = 1;var b = a;a = 2;console.log(a, b); // 2, 1 ,a b指向不同的数据
// 援用类型指向同一份数据var a = {c: 1};var b = a;a.c = 2;console.log(a.c, b.c); // 2, 2 全是2,a b指向同一份数据
三、深拷贝和浅拷贝的区别
浅拷贝:只拷贝一层。
深拷贝:无限极拷贝。
四、深度拷贝的四个例子
办法一:
function clone(source){ if (!isObject(source)) return source;//参数校验更加优良 var target={}; for(var i in source){ if(source.hasOwnProperty(source){ if(typeof source[i] === 'object'){ // Object.prototype.toString.call(source[i] === '[Object Object]' target[i] = clone(source[i]) }else{ target[i] = source[i]; } } return target;}function isObject(obj){ return Object.prototype.toString.call(obj === '[Object Object]'}
办法二:
function cloneJSON (source){ return JSON.parse(JSON.stringfy(source));}
办法三:
function cloneLoop(x) { const root = {}; // 栈 const loopList = [ { parent: root, key: undefined, data: x, } ]; while(loopList.length) { // 深度优先 const node = loopList.pop(); const parent = node.parent; const key = node.key; const data = node.data; // 初始化赋值指标,key为undefined则拷贝到父元素,否则拷贝到子元素 let res = parent; if (typeof key !== 'undefined') { res = parent[key] = {}; } for(let k in data) { if (data.hasOwnProperty(k)) { if (typeof data[k] === 'object') { // 下一次循环 loopList.push({ parent: res, key: k, data: data[k], }); } else { res[k] = data[k]; } } } } return root;}
办法四:
// 放弃援用关系function cloneForce(x) { // ============= const uniqueList = []; // 用来去重 // ============= let root = {} // 循环数组 const loopList = [ { parent: root, key: undefined, data: x, } ]; while(loopList.length) { // 深度优先 const node = loopList.pop(); const parent = node.parent; const key = node.key; const data = node.data; // 初始化赋值指标,key为undefined则拷贝到父元素,否则拷贝到子元素 let res = parent; if (typeof key !== 'undefined') { res = parent[key] = {}; } // ============= // 数据曾经存在 let uniqueData = find(uniqueList, data); if (uniqueData) { parent[key] = uniqueData.target; break; // 中断本次循环 } // 数据不存在 // 保留源数据,在拷贝数据中对应的援用 uniqueList.push({ source: data, target: res, }); // ============= for(let k in data) { if (data.hasOwnProperty(k)) { if (typeof data[k] === 'object') { // 下一次循环 loopList.push({ parent: res, key: k, data: data[k], }); } else { res[k] = data[k]; } } } } return root;}function find(arr, item) { for(let i = 0; i < arr.length; i++) { if (arr[i].source === item) { return arr[i]; } } return null;}
援用文章:https://segmentfault.com/a/11...