<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path> </svg> <p></p>
讯享网
1.1 栈(stack)和堆(heap)
- 栈(stack):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;
- 堆(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表
1.2 基本数据类型和引用数据类型
1.2.1 概念
- 基本数据类型:Number、String、Boolean、Null、 Undefined、Symbol(ES6);
- 引用数据类型:Object、Array、Function、Date、RegExp、Map、Set等。
1.2.2 区别
两者区别:
- 内存地址分配:
1)基本数据类型:将值存储在栈中 ,栈中存放的是对应的值
2)引用数据类型:将对应的值存储在堆中,栈中存放的是指向堆内存的地址- 赋值变量:
1)基本数据类型:是生成相同的值,两个对象对应不同的地址
2)引用数据类型:是将保存对象的内存地址赋值给另一个变量。也就是两个变量指向堆内存中同一个对象
讯享网
总结:
a是基本类型,存储在栈中;把a赋值给b,虽然两个变量的值相等,但是两个变量保存了两个不同的内存地址。
1.2.3 基本类型赋值方式
1.2.4 引用类型赋值方式
理解:obj1是引用类型,将数据存放在堆内存中,而栈中存放的是内存地址.在obj1赋值给obj2,实际是将obj1的引用地址复制了一份给了obj2,实际上他们共同指向了同一个堆内存对象,所以更改obj2会对obj1产生影响

2.1 概念理解
- 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
- 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
借助ConardLi大佬以下两张图片,帮我们更好的理解两者的含义:



总而言之,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
2.2 深浅拷贝区别
- 浅拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。
- 深拷贝:从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响。
- Object.assign()
- 扩展运算符(…)
- Array.prototype.concat()
- Array.slice()
3.1 Object.assign()
object.assign 是 ES6 中 object 的一个方法,该方法可以用于JS 对象的合并等多个用途,其中一个用途就是可以进行浅拷贝。
object.assign 的语法为:Object.assign(target, …sources)
讯享网
运行结果如下:

注意:
- Object.assign()不会拷贝对象的继承属性;
- Object.assign()不会拷贝对象的不可枚举的属性;
- Object.assign()可以拷贝 Symbol 类型的属性。
3.2 扩展运算符(…)
扩展运算符的语法为:let cloneObj = { …obj };
运行结果如下:


注意:扩展运算符 和 object.assign 有同样的缺陷,也就是实现的浅拷贝的功能差不多,但是如果属性都是基本类型的值,使用扩展运算符进行浅拷贝会更加方便。
3.3 Array.prototype.concat()
讯享网
运行结果如下:

注意:数组的 concat 方法其实也是浅拷贝,所以连接一个含有引用类型的数组时,需要注意修改原数组中的元素的属性,因为它会影响拷贝之后连接的数组。不过 concat 只能用于数组的浅拷贝,使用场景比较局限。
3.4 Array.prototype.slice()
slice 的语法为:arr.slice(begin, end);
运行结果如下:

注意:slice 方法也比较有局限性,因为它仅仅针对数组类型。slice 方法会返回一个新的数组对象,这一对象由该方法的前两个参数来决定原数组截取的开始和结束位置,是不会影响和改变原始数组的。但是,数组元素是引用类型的话,也会影响到原始数组。
- JSON.parse(JSON.stringify(obj))
- 递归方法
- 函数库 lodash
4.1 JSON.parse(JSON.stringify(obj))
讯享网
运行结果如下:

但是,JSON.stringify并不是那么完美的,它也有局限性。
- 拷贝的对象的值中如果有函数、undefined、symbol 这几种类型,经过 JSON.stringify 序列化之后的字符串中这个键值对会消失;
- 拷贝 Date 引用类型会变成字符串;
- 无法拷贝不可枚举的属性;
- 无法拷贝对象的原型链;
- 拷贝 RegExp 引用类型会变成空对象;
- 对象中含有 NaN、Infinity 以及 -Infinity,JSON 序列化的结果会变成 null;
- 无法拷贝对象的循环应用,即对象成环 (obj[key] = obj)。
4.2 手写递归
讯享网
4.2 函数库lodash
lodash是一个著名的javascript原生库,不需要引入其他第三方依赖。是一个意在提高开发者效率,提高JS原生方法性能的JS库。简单的说就是,很多方法lodash已经帮你写好了,直接调用就行,不用自己费尽心思去写了,而且可以统一方法的一致性。Lodash使用了一个简单的_ 符号,就像Jquery的 $ 一样,十分简洁。lodash函数库提供 _.cloneDeep用来做深拷贝。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/191272.html