1.ES6中新增了扩展运算符,可以实现对数组和对象的复制,这种复制是深拷贝还是浅拷贝?
let arr = [10,20,30]
let arr0 = [...arr]
console.log(arr === arr0) // false
arr和arr0的比较结果为false,那么我们初步判断二者不是同一个地址引用,接下来修改arr0,来观测arr是否发生改变:
arr0 = 'hello'
console.log(arr)
修改arr0
的值,并不影响arr
值的改变,是不是说明扩展运算符的复制就是深拷贝呢?
接下来,测试一下复杂的数组:
let arr = [[10], [20], [30]],
arr0 = [...arr]
console.log(arr === arr0) // false
arr0[0][0] = 'hello'
console.log(arr)
console.log(arr0)
我们修改数组的第一个元素,发现两个数组的值都发生了改变,说明扩展符不是深拷贝
,依然是浅拷贝
2.总结,哪些方案可以实现“浅拷贝”和“深拷贝”
浅拷贝
Object.assign()
该方法用于对象复制
时,是浅拷贝
- 数组的①
slice()
方法、②concat()
方法、③Array.from()
方法、④扩展运算符
都算是浅拷贝
// target--->目标对象
// source--->源对象
// 返回值:target,即目标对象
Object.assign(target, ...sources)
// slice() 方法可从已有的数组中返回选定的元素。
// 语法:arrayObject.slice(start,end)
// 返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素
var arr=['aa','bb','cc','dd','ee','ff'];
var data=arr.slice(2,4);
新数组data结果为: ["cc", "dd"]
// 合并三个数组的值
var hege = ["Cecilie", "Lone"];
var stale = ["Emil", "Tobias", "Linus"];
var kai = ["Robin"];
var children = hege.concat(stale,kai);
Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组
let obj = {
'0': 'james',
'1': 'kobe',
'length': 2
}
let arr1 = Array.from(obj)
console.log(arr1); // ["james", "kobe"]
// 对象的属性为其他的字符串类型
let obj = {
'name1': 'james',
'name2': 'kobe',
length: 2
}
let arr2 = Array.from(obj)
console.log(arr2); // [undefined, undefined]
// 没有length的对象
let obj = {
'0': 'james',
'1': 'kobe'
}
let arr = Array.from(obj)
console.log(arr); // []
// set, map, array
let arr = [1,2,3]
let set = new Set(arr);
let arr1 = Array.from(set)
console.log(arr1); ///[1,2,3]
深拷贝
目前能实现深拷贝的办法
- 递归方案(通过循环一层一层的进行拷贝)
- JSON.parse()方法,但有缺点,对于
undefined、function、symbol
会被忽略