JS数据类型划分:
基本数据类型:string,number,boolean,null,undefined
引用数据类型:Object(包括 Array,String,Function,Math,Date等)
JS内存分为堆(heap)和栈(stack)
栈:由系统自动分配,自动回收,效率高,但容量小。
堆:由程序员手动分配内存,并且手动销毁(高级语言如JS中有垃圾自动回收机制),效率不如栈,但容量大。
JS的基本类型分配在栈中。
而因为引用类型大小的不固定,系统将存储该引用类型的地址存在栈中,并赋值给变量本身,而具体的内容存在堆中。
所以当访问一个对象的时候,先访问栈中它的地址,然后按照这个地址去堆中找到它的实际内容。
当复制的时候,对于基本类型的变量,系统会为新的变量在栈中开辟一个新的空间,赋予相同的值,然后这两个变量就各自独立,毫无牵连。
而对于引用类型的变量,新的变量复制的是那个对象在堆中的地址,这两个变量指向的是同一个对象。
JS的基本类型不存在浅拷贝还是深拷贝的问题,主要是针对于对象,比如一般的对象,和特殊的数组对象。
浅拷贝是指复制对象的时候,指对第一层键值对进行独立的复制。
浅拷贝实现方式1:
1 | function shaCopy(source){ //浅拷贝 |
浅拷贝实现方式2:
Object.assign是ES6的新函数。
Object.assign()
方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
但是 Object.assign()
进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
1 | Object.assign(target, ...sources) |
参数:
target:目标对象。
sources:任意多个源对象。
返回值:目标对象会被返回。
1 | var obj1={ name:"jack", friend:{ name:"tom",age:18 }}; |
那如何完全独立地拷贝出一份呢?这也就是所谓的深拷贝。
深拷贝实现方式1:
Object.assign();
当对象只有一层时,Object.assign()也能实现深拷贝。
深拷贝实现方式2:
用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象。
但是只有对象内属性值不为undefined和Function时可用。
深拷贝实现方式3:
递归实现
1 | function deepClone(source) { |
深拷贝实现方式4:
jquery 有提供一个$.extend可以用来做 Deep Copy。
1 | var $ = require('jquery'); |
深拷贝实现方式5:
另外一个很热门的函数库lodash,也有提供_.cloneDeep用来做 Deep Copy。
1 | var _ = require('lodash'); |
- 本文作者: Tsailor
- 本文链接: http://tsailor.github.io/2020/06/26/JS深拷贝与浅拷贝/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!