文章首次发表于 我的博客,系列文章目录:github.com/funnycoders…前端
基本类型数据保存在在栈内存中 引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中。git
为何基本数据类型存在栈内存,引用数据类型存在堆内存?github
基本类型赋值,系统会为新的变量在栈内存中分配一个新值,这个很好理解。 引用类型赋值,系统会为新的变量在栈内存中分配一个值,这个值仅仅是指向同一个对象的引用,和原对象指向的都是堆内存中的同一个对象。面试
var obj1 = new Object(); var obj2 = obj1; obj1.name = 'lucyStar'; console.log(obj2.name); // lucyStar 复制代码
咱们能够看到,obj1保存了一个对象的实例,这个值被赋值到 Obj2中。赋值操做完成后,两个变量实际引用的是同一个对象,改变了其中一个,会影响另一个值。数组
什么是浅拷贝? 若是是对象类型,则只拷贝一层,若是对象的属性又是一个对象,那么此时拷贝的就是此属性的引用。微信
简单实现一个浅拷贝markdown
function shadowCopy(obj) { const newObj = {}; for(let prop in obj) { if(obj.hasOwnProperty(prop)){ newObj[prop] = obj[prop]; } } return newObj; } const obj1 = { name: 'litterStar', a: { b: '1' } }; const obj2 = shadowCopy(obj1); obj2.name = 'lucyStar'; obj2.a.b = '2'; console.log(obj1); // { name: 'litterStar', a: { b: '2' } } console.log(obj2); // { name: 'lucyStar', a: { b: '2' } } 复制代码
能够看到修改obj2
的name
属性不会影响 obj1
,可是修改 obj2
的 a属性(是个对象)的 b,就会影响 obj1.a.b函数
使用下面这些函数获得的都是浅拷贝:oop
Object.assign
Array.prototype.slice()
, Array.prototype.concat()
什么是深拷贝? 浅拷贝是只拷贝一层,深拷贝会拷贝全部的属性。深拷贝先后两个对象互不影响。post
深拷贝的实现
JSON.parse(JSON.stringify())
JSON.parse(JSON.stringify())
有存在如下问题:
尝试本身写一个深拷贝,须要考虑下面这几种状况
obj.prop1 = obj
function deepCopy(originObj, map = new WeakMap()) { // 判断是否为基本数据类型 if(typeof originObj === 'object') { // 判断是都否为数组 const cloneObj = Array.isArray(originObj) ? [] : {}; // 判断是否为循环引用 if(map.get(originObj)) { return map.get(originObj); } map.set(originObj, cloneObj); for(const prop in originObj) { cloneObj[prop] = deepCopy(originObj[prop], map); } return cloneObj; } else { return originObj; } } const obj1 = { a: '111', } obj1.obj2 = obj1; const aa = deepCopy(obj1); console.log(aa); // { a: '111', obj2: [Circular] } 复制代码
上面只是实现一个简单的深拷贝,不少状况未考虑到,好比 特殊的数据类型及兼容性的处理,更多细节的实现能够参考 lodash 中的 cloneDeep方法。
和原数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含对象 | |
---|---|---|---|
赋值 | 是 | 改变会使原数据一同改变 | 改变会使原数据一同改变 |
浅拷贝 | 否 | 改变不会使原数据一同改变 | 改变会使原数据一同改变 |
深拷贝 | 否 | 改变不会使原数据一同改变 | 改变不会使原数据一同改变 |
备注:markdown 表格在 tableconvert.com/ 该网站生成,很方便。
最近发起了一个100天前端进阶计划,主要是深挖每一个知识点背后的原理,欢迎关注 微信公众号「牧码的星星」,咱们一块儿学习,打卡100天。