上一篇文章还是沉浸再要过年的喜庆气氛当中,但怎么都没有想到疫情是如此的严重,还是希望各位珍爱生命远离病毒吧!,回顾一下过去的几个月,还好像再眼前,不禁感叹道时间过得实在太快,最近也在持续关注各大厂的招聘情况,感觉疫情之下,机会更少了,要求更多了,但是话又说回来,上天对每个人都是公平的,机会是对等的,只有不断地充实自己才是王道。所以我又来给各位灌毒鸡汤来了,干了这碗,咱们开始讲今天的主题,也就是我最近再啃得原生js。
-
数据类型
数据类型分为两种,基本数据类型和引用数据类型,基本数据类型存储直接存储在栈内存中,而对于引用类型来说,它在栈内存中仅仅存了一个引用,而真正得数据存储在堆内存中。看一下示例图
引用类型就是存在堆内存中,两个对象是在用指针指向同一个堆内存得地址
-
浅拷贝
既然要说深拷贝,那估计大家都知道肯定有浅拷贝啊,那什么是浅拷贝呢?
// 基本类型得的浅拷贝 var a = 5 ; var b = a ; b = 3 console.log(a); // 5 console.log(b) // 3 // 引用类型的浅拷贝 var obj = { name:'yuhior', age:18, class:'三年二班' } var obj2 = obj ; obj2.name = '张三了'; console.log(obj.name) // 张三了 console.log(obj2.name) // 张三了
上边我们发现 基本类型由于存储在栈内存中,是两个相对独立的数据,所以更改一个另一个并不会改变,但是引用类型的obj 改变的name ,将 obj 赋予 obj2 的时候,我们其实仅仅只是将 obj 存储在栈堆中的的引用赋予了 obj2 ,而两个对象此时指向的是在堆内存中的同一个数据,所以当我们修改任意一个值的时候,修改的都是堆内存中的数据。我称 这种 = 只拷贝对象的引用,而不深层次的拷贝对象的值叫浅拷贝
-
深拷贝
在实际项目中,尤其是使用vue ,数据双向绑定的框架时,尤其明显的能感知到每个对象指向一个堆内存,一个改变另一些全部改变,根本不便于操作 。所以我们要深拷贝,我们要自由 哈哈哈哈哈。深拷贝就不会拷贝引用类型的引用,而是将引用类型的值全部拷贝一下,形成一个全新的堆内存存储。
-
深拷贝的实现方法
-
低配版 JSON.stringify()和JSON.parse()
var obj = { name:'yuhior', age:18, class:'三年二班' } var obj2 = JSON.parse(JSON.stringify(obj)); obj2.name = '张三了'; console.log(obj.name) // yuhior console.log(obj2.name) // 张三了
缺点:不可以拷贝undefined 、function 、RegExp类型 的
var obj = undefined; var obj1 = JSON.parse(JSON.stringify(obj)); // 直接报错 // VM4562:1 Uncaught SyntaxError: Unexpected token u in JSON at position 0 // at JSON.parse (<anonymous>) // at <anonymous>:1:17
-
Object.assign (target,source)
var obj1 = { a: 1, b: 2, c: 3 } var obj2 = Object.assign({}, obj1); obj2.b = 5; console.log(obj1.b); // 2 console.log(obj2.b); // 5
缺点:可以看到对于一层对象来说是没有任何问题的,但是如果对象的属性对应的是其它的引用类型的话,还是只拷贝了引用,修改的话还是会有问题
var obj1 = { // 来一个多层的 a: 10, b: 11, c: ['a','b','c'] } var obj2 = Object.assign({}, obj1); obj2.c[1] = 6; console.log(obj1.c); // ["a", 6, "c"] console.log(obj2.c); // ["a", 6, "c"] // 两个都改变了说明还是引用了
-
递归拷贝 ,也是面试官常考的 ,我们还是先来举个栗子,毕竟学习了,还能吃栗子还是很爽的把 ,哈哈哈哈
// 写一个深拷贝的方法把 function depClone(tar){ let result; // tar如果是一个对象的话 if(typeof(tar)==='object'){ // typeof(Array) ==='object'; 如果是一个数组 if(Array.isArray(tar)){ result = []; // 将result 设定为数组 并执行遍历 for(let i in tar){ //进行克隆数组中的每一项 result.push(deepClone(tar[i])); } // 如果是null的话,那就直接赋值null }else if(tar === null){ result = null; // 判断如果当前的值是一个RegExp对象的话,直接赋值 }else if(tar.constructor===RegExp){ result = tar; //最后就是普通的对象了,直接进行循环,递归赋值所有的值 }else{ result = {}; for(let i in tar){ result[i] = deepClone(tar[i]); } } // 如果不是对象的话,那就是一个基本类型了,那就直接赋值被 }else{ result = tar ; } // 终于到回归结果的时候啦 return result; }
锅都准备好啦,那就赶紧做个饭试一下把!!!
// 有一个对象 多层嵌套,还含有undefined var obj = { a:{ b:/a/, c:undefined, d:null }, b:function(){ console.log(this.a); }, c:[ { b:/a/, c:undefined, d:null }, 'a', 3 ] }; var obj1 = deepClone(obj); console.log(obj2); // 相信你勤快的小手,自己打印一下看看把
-