前言:
本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽。
本篇文章为您分析一下原生JS写对象混合与克隆
对象混合
页面中如下需求
var obj1 = { x: 1, y: "a" } var obj2 = { x: "b", o: 6 }
页面上有两个对象
我们要把这两个对象混合成一个
形成如下结构:
我们要把这两个对象混合成一个
形成如下结构:
// 将obj2混合到obj1中 obj = { x: "b", y: "a", o: 6 }
参考代码:
// ES5之前的版本 function mixin(obj1, obj2){ // 第一步: 创建一个对象 var newObj = {}; // 第二步: 循环obj2中的对象 for(var prop in obj2){ // 第三步: 将obj2中的属性添加到新创建爱对象中 newObj[prop] = obj2[prop]; } // 第四步: 循环obj1中的对象 for(var prop in obj1){ // 第五步: 看看obj1中的属性在不在obj2中,如果不在就将他加入的新的对象中 if(!(prop in obj2)){ newObj[prop] = obj1[prop]; } } // 最后返回这个新的对象 return newObj; } // ES6版本 // function mixin(obj1, obj2){ // return Object.assgin({},obj1,obj2); // }
在页面中调用
var obj = mixin(obj1, obj2); console.log(obj);
图片
对象克隆
页面中如下需求
var obj = { x: "123", y: 456, objSon: { c: "a" } } var newObj = clone(obj); // 要求实现newObj中有obj的所有属性 // 并且newObj.objSon !== obj.objSon;
下面来看看代码
function clone(obj) { var newObj = {}; for (var prop in obj) { newObj[prop] = obj[prop]; } }
下面来看看效果
图片
如果obj是一个数字会怎么样呢?
var obj = 123;
var obj = 123;
图片
为什么会是一个对象呢?
因为我们在function中创建了一个对象
如果obj是一个字符串呢? var obj = "abcdefg";
因为我们在function中创建了一个对象
如果obj是一个字符串呢? var obj = "abcdefg";
图片
如果obj是一个数组又会怎么样呢?
var obj = [12,35,65,87,1,3];
var obj = [12,35,65,87,1,3];
图片
他克隆出来就是一个伪数组了
而且length属性还得不到
而且length属性还得不到
图片
鉴于上面出现的多种情况
我们刚刚写的代码(只是假设他是普通对象,还不是数组对象,数组本身也是对象嘛)就不足以完成一个完整的克隆函数
因此,我们要进行判断
我们刚刚写的代码(只是假设他是普通对象,还不是数组对象,数组本身也是对象嘛)就不足以完成一个完整的克隆函数
因此,我们要进行判断
function clone(obj) { if (Array.isArray(obj)) { // 如果他是一个数组 return obj.slice(); // 复制数组 } else if (typeof obj === "object") { // 如果他是一个普通对象 var newObj = {}; // 定义一个对象 for (var prop in obj) { // 循环obj newObj[prop] = obj[prop]; // 添加属性 } return newObj; // 返回 } else { // 函数、原始类型 return obj; // 直接返回 } }
在页面上打印newObj
图片 判断newObj === obj
现在来看这个克隆更加优化了
但是并没有完整
如果obj的属性也是一个对象呢?
但是并没有完整
如果obj的属性也是一个对象呢?
var obj = { x: "123", y: 456, subObj: { a: "abc" } }
newObj本身是不等于obj的,因为是克隆嘛,产生了一个新的对象
但是它里面的subObj属性的地址是一样的
如果我们给newObj.subObj.a ==="XXX";赋值了。
他会导致:obj.subObj.a也跟着改变。
所以我们把目前我们写的这种方式叫做 [浅度克隆]
还有一种克隆叫 [深度克隆] 就是要对他属性做深度处理
因此这个函数还需要一个参数来判断他是否需要深度克隆
但是它里面的subObj属性的地址是一样的
如果我们给newObj.subObj.a ==="XXX";赋值了。
他会导致:obj.subObj.a也跟着改变。
所以我们把目前我们写的这种方式叫做 [浅度克隆]
还有一种克隆叫 [深度克隆] 就是要对他属性做深度处理
因此这个函数还需要一个参数来判断他是否需要深度克隆
function clone(obj, deep) { if (Array.isArray(obj)) { // 如果他是一个数组 return obj.slice(); // 复制数组 } else if (typeof obj === "object") { // 如果他是一个普通对象 var newObj = {}; // 定义一个对象 for (var prop in obj) { // 循环obj if (deep){ // 如果是深度克隆的话,我们把这个属性的值再克隆一遍【递归】 newObj[prop] = this.clone(obj[prop], deep); }else { newObj[prop] = obj[prop]; // 添加属性 } } return newObj; // 返回 } else { // 函数、原始类型 return obj; // 直接返回 【递归的终止条件】 } } // 再传入第二个参数 var newObj = clone(obj, true);
图片 newObj。subObj' ===
针对数组如何深度克隆
function clone(obj, deep) { if (Array.isArray(obj)) { // 如果他是一个数组 if(deep){ // 深度克隆 var newArr = []; //定义一个空数组 for(var i = 0; i< obj.length; i++){ // 循环obj的每一项 newArr[i].push(clone(obj[i],deep)); // pun数组 } }else { return obj.slice(); // 复制数组 } } else if (typeof obj === "object") { // 如果他是一个普通对象 var newObj = {}; // 定义一个对象 for (var prop in obj) { // 循环obj if (deep){ // 如果是深度克隆的话,我们把这个属性的值再克隆一遍【递归】 newObj[prop] = this.clone(obj[prop], deep); }else { newObj[prop] = obj[prop]; // 添加属性 } } return newObj; // 返回 } else { // 函数、原始类型 return obj; // 直接返回 【递归的终止条件】 } }
图片
这样就完成了对象的克隆
来源:https://www.cnblogs.com/qq4297751/p/12630364.html