【JavaScript 深拷贝】$.extend() 方法、自封装函数(进来拿代码套用啦!)

    技术2022-07-11  106

    搜集来源:(代码中的同类变量已被我修改优化为同名变量)

    【JS】深拷贝与浅拷贝的区别,实现深拷贝的几种方法(递归一)js实现深拷贝(递归二、树广度一)JS实现深拷贝(递归一、树深度一)深度优先遍历,广度优先遍历实现对象的深拷贝(树深度二、树广度二)

    关于赋值、浅拷贝、深拷贝的区别


    文章目录

    JSON 对象方法防坑注意: 【jQuery】extend()方法递归函数(一)递归函数(二)【DFS】树深度优先遍历(一)【DFS】树深度优先遍历(二)【BFS】树广度优先遍历(一)【BFS】树广度优先遍历(二)


    JSON 对象方法

    Object.prototype.deepClone = function() { return JSON.parse(JSON.stringify(this)); }

    防坑注意:


    【jQuery】extend()方法

    无论修改拷贝对象第几层嵌套层,原对象均不会被影响:PS:别忘了引入【jq库】

    递归函数(一)

    无论修改拷贝对象第几层嵌套层,原对象均不会被影响:【缺点】当数据的层次很深,会栈溢出,所以最好用【DFS / BFS】 // 递归封装深拷贝 function deepClone(obj) { if (obj === null) { return null; } else if (typeof obj !== 'object') { // 不再具有下一层次 return obj; } else if (obj.constructor === Date) { return new Date(obj); } // 保持继承链 var objClone = new obj.constructor (); for (var k in obj) { // 不遍历其原型链上的属性 if (obj.hasOwnProperty(k)) { // 判断obj子元素是否为对象,如果是,递归复制 if (obj[k] && typeof obj[k] === 'object') { objClone[k] = deepClone(obj[k]); } else { objClone[k] = obj[k]; } // 简写 // objClone[k] = typeof obj[k] === 'object' ? deepClone(obj[k]) : obj[k]; } } // 返回深度克隆后的对象 return objClone; };

    递归函数(二)

    演示图与上面一样就不发了【缺点】当数据的层次很深,会栈溢出,所以最好用【DFS / BFS】 // 创建对元素进行类型判断的函数 function getType(obj) { // tostring会返回对应不同的标签的构造函数 var _toString = Object.prototype.toString; var map = { '[object Boolean]' : 'boolean', '[object Number]' : 'number', '[object String]' : 'string', '[object Function]' : 'function', '[object Array]' : 'array', '[object Date]' : 'date', '[object RegExp]' : 'regExp', '[object Undefined]' : 'undefined', '[object Null]' : 'null', '[object Object]' : 'object' }; if (obj instanceof Element) { return 'element'; } return map[_toString.call(obj)]; } // 递归封装深拷贝 function deepClone(obj) { var type = getType(obj); var objClone; if (type === 'array') { objClone = []; } else if (type === 'object') { objClone = {}; } else { // 不再具有下一层次 return obj; } // 类型为数组或对象时的递归复制 if (type === 'array') { for (var i = 0, len = obj.length; i < len; i++) { objClone.push(deepClone(obj[i])); } } else if (type === 'object') { for (var k in obj) { objClone[k] = deepClone(obj[k]); } } // 返回深度克隆后的对象 return objClone; }

    【DFS】树深度优先遍历(一)

    // 深度优先深度克隆, 利用栈的方式实现 // 防栈溢出 function deepClone(obj) { var objClone = {}; // 栈 var loopList = [{ parent: objClone, key: undefined, data: obj, }]; while (loopList.length) { // 深度优先 var node = loopList.pop(); var parent = node.parent; var key = node.key; var data = node.data; // 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素 var res = parent; if (typeof key !== 'undefined') { res = parent[key] = {}; } for (var 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 objClone; }

    【DFS】树深度优先遍历(二)

    // 创建对元素进行类型判断的函数 function getType(obj) { // tostring会返回对应不同的标签的构造函数 var _toString = Object.prototype.toString; var map = { '[object Boolean]' : 'boolean', '[object Number]' : 'number', '[object String]' : 'string', '[object Function]' : 'function', '[object Array]' : 'array', '[object Date]' : 'date', '[object RegExp]' : 'regExp', '[object Undefined]' : 'undefined', '[object Null]' : 'null', '[object Object]' : 'object' }; if (obj instanceof Element) { return 'element'; } return map[_toString.call(obj)]; } // 深度优先深度克隆, 利用栈的方式实现 // 解决【递归、对象环、边界处理(比如函数,Set等)、防栈溢出】问题 function deepClone(obj) { var type = getType(obj); var objClone = {}; // 用于存储复制过程中访问过的对象的队列,避免对象环的问题 var visitQueue = []; if (type === 'array' || type === 'object') { var index = visitQueue.indexOf(obj); if (index > -1){ objClone = visitQueue[index] } else { visitQueue.push(obj); for (var key in obj) { objClone[key] = deepClone(obj[key], visitQueue); } } } else if (type === 'function') { // 处理函数 objClone = eval( '(' + obj.toString() + ')'); } else { // 处理原始值 objClone = obj; } // 返回深度克隆后的对象 return objClone; }

    【BFS】树广度优先遍历(一)

    // 广度优先深度克隆, 利用队列的方式实现 // 利用objClone建立一个与原对象相同的数据结构, 遇到可处理的值(比如原始值,函数,就处理后赋值到相应的节点下) function deepClone(obj) { var objClone = {}; // 进队列 var originQueue = [obj]; // 同时objClone也跟着一起进队列 var copyQueue = [objClone]; // 以下两个队列用来保存复制过程中访问过的对象,以此来避免对象环的问题(对象的某个属性值是对象本身) var visitQueue = []; var copyVisitQueue = []; while (originQueue.length > 0) { var _obj = copyQueue.shift(); var _data = originQueue.shift(); copyVisitQueue.push(_obj); visitQueue.push(_data); for (var k in _data) { var _value = _data[k]; if (typeof _value !== 'object') { _obj[k] = _value; } else { // 使用indexOf可以发现数组中是否存在相同的对象(实现indexOf的难点就在于对象比较) var index = visitQueue.indexOf(_value); if (index >= 0) { // 出现环的情况不需要再取出遍历 _obj[k] = copyVisitQueue[index]; } else { originQueue.push(_value); _obj[k] = {}; copyQueue.push(_obj[k]); } } } } // 返回深度克隆后的对象 return objClone; }

    【BFS】树广度优先遍历(二)

    // 创建对元素进行类型判断的函数 function getType(obj) { // tostring会返回对应不同的标签的构造函数 var _toString = Object.prototype.toString; var map = { '[object Boolean]' : 'boolean', '[object Number]' : 'number', '[object String]' : 'string', '[object Function]' : 'function', '[object Array]' : 'array', '[object Date]' : 'date', '[object RegExp]' : 'regExp', '[object Undefined]' : 'undefined', '[object Null]' : 'null', '[object Object]' : 'object' }; if (obj instanceof Element) { return 'element'; } return map[_toString.call(obj)]; } // 广度优先深度克隆, 利用队列的方式实现 // 利用objClone建立一个与原对象相同的数据结构, 遇到可处理的值(比如原始值,函数,就处理后赋值到相应的节点下) function deepClone(obj) { var objClone = {}; // 进队列 var originQueue = [obj]; // 同时objClone也跟着一起进队列 var copyQueue = [objClone]; // 用于存储复制过程中访问过的对象的队列,避免对象环的问题 var visitQueue = []; while(originQueue.length){ var _obj = originQueue.shift(); var _data = copyQueue.shift(); if (getType(_obj) === 'array' || getType(_obj) === 'object') { for(item in _obj){ var val = _obj[item]; if (getType(val) === 'object') { var index = visitQueue.indexOf(val); if (~index) { // 对象环 _data[item] = visitQueue[index]; } else { // 新的对象,给objClone一个对应属性的空对象 originQueue.push(val); _data[item] = {}; copyQueue.push(_data[item]); visitQueue.push(val); } } else if (getType(val) === 'array') { originQueue.push(val); _data[item] = []; copyQueue.push(_data[item]) } else if (getType(val) === 'function') { // 处理函数 _data[item] = eval( '(' + val.toString() + ')'); } else { // 处理原始值 _data[item] = val; } } } else if (getType(obj) === 'function') { // 处理函数 _data = eval( '(' + _obj.toString() + ')'); } else { // 处理原始值 _data = _obj; } } // 返回深度克隆后的对象 return objClone; }
    Processed: 0.019, SQL: 10