深拷贝和浅拷贝
在很多实例方法(非静态方法/构造函数原型中的方法)中都体现了深拷贝和浅拷贝【了解原型】。并且深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。
了解深拷贝和浅拷贝之前,首先要知道内存的空间分布
内存分为5个区:
①栈区stack: 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等
②堆区heap:一般由程序员分配释放, 若程序员不释放,程序结束时可能由系统回收
③全局区(又称静态存储区)(static):全局变量和静态变量的存储是放在一块的
④文字常量区 :常量字符串就是放在这里的, 程序结束后由系统释放;
⑤代码段:存放函数体的二进制代码;
- 深拷贝
拷贝值,两个指针指向不同的内存,这两块内存中的数据是一样的 - 浅拷贝
拷贝指针,两个指针指向同一块内存
注意: 赋值传递的是栈区的值
方法
- 浅拷贝方法
var a = {name:"lily"} var b = a; b === a //true
- 深拷贝方法
①将json字符串解析成对象JSON.parse()
var a = {}
var c = JSON.parse(JSON.stringify(a))
c === a //测试地址是否相等 false
②{…}es6对象中的扩展运算符,用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
let d = { a: 1, b: 2 };
let e = { ...d }; // { a: 1, b: 2 }
d === e//false
③ Object.assign(target,sourse)
用于对象的合并,第一个参数是目标对象,后面的参数都是源对象,前提是object只有一层的时候是深拷贝(var obj={}),多层时进行浅拷贝(var obj={a:{}})。学习参考:浅拷贝与深拷贝的区别
var obj1 = { a: 1, b: 2 };
var obj2 = Object.assign({},obj1)
obj2 === obj1//false
④函数库lodash
该库提供深拷贝方法_.cloneDeep。
var_ = require('lodash');
var obj1 = {
a:1,
b:{f:{g:1}},
c:[1,2,3]
}
var obj2 = _.cloneDeep(obj1);
obj1.b.f === obj2.b.f//false
这里分析几个Array的方法,其他实例方法详细了解在MDN
类型 | 方法名 | 简单说明 |
---|---|---|
浅拷贝 | Array.from() | (es6)从一个类似数组或可迭代对象创建一个新的 |
浅拷贝 | arr.pop() | 出栈,将数组末尾的值删除并且返回 |
浅拷贝 | arr.shift() | 出队,将数组开头的值删除并且返回 |
浅拷贝 | arr.reverse() | 数组元素顺序反转,返回反转后的数组 |
浅拷贝 | arr.sort() | 排序,如果没有参数,将会按照字符串(如果是其他类型转换成字符串)的顺序/ASCII码表给数组元素排序,如果参数由比较器函数,则按照比较器函数规则进行排序。 |
浅拷贝 | arr.splice(begin,len,item…) | 可以实现删除,替换,插入元素,begin开始位置,len删除的元素个数,item插入的元素(不限),返回删除元素组成的数组 |
深拷贝 | arr.slice(begin,end) | 从指定数组获取子数组,begin开始位置,end结束位置,裁剪不包含结束位置,end可以省略,截取到数组末尾 |
深拷贝 | arr.concat() | 合并数组,返回合并后的数组 |