(1)复本字符串
字符串是A43EI235E的正则表达式,间接复本不然,而已复本了对准下层计算机程序的操作符,而并非布季夫两个崭新的字符串。
onst a1 = [1, 2];
const a2 = a1;
a2[0] = 2;
a1 // [2, 2]
下面标识符中,a2并并非a1的布季夫,而要对准同这份统计数据的另两个操作符。修正a2,会间接引致a1的变动。
ES5 根本无法用大别列兹尼区来复本字符串。
const a1 = [1, 2];
const a2 = a1.concat();
a2[0] = 2;
a1 // [1, 2]
下面标识符中,a1会回到原字符串的布季夫,再修正a2就不能对a1造成负面影响。
扩充操作符提供更多了复本字符串的方便快捷读法。
const a1 = [1, 2];
// 读法一
const a2 = [...a1];
// 读法二
const [...a2] = a1;
下面的三种读法,a2都是a1的布季夫。
第一类及json字符串的复本,Object.assign() {…obj} JSON.Parse 等三种复本的差别
let obj = {
age: 10
}
let obj1 = {
grade: 1,
name: {
first: bob
}
}
let objS = obj1
let objA = Object.assign(obj, obj1)
let objJ = JSON.parse(JSON.stringify(obj1))
let objK = { ...obj1 }
console.log(objA)
console.log(objJ)
console.log(objK)
obj1.grade = 9
obj1.name.first = chris
console.log(objS)
console.log(objA)
console.log(objJ)
console.log(objK)
打印结果:
{ age: 10, grade: 1, name: { first: bob } }
{ grade: 1, name: { first: bob } }
{ grade: 1, name: { first: bob } }
{ grade: 9, name: { first: chris } }
{ age: 10, grade: 1, name: { first: chris } }
{ grade: 1, name: { first: bob } }
{ grade: 1, name: { first: chris } }
结论: 由于第一类创建在堆上 栈上的变量保存其地址 所以也叫操作符变量
浅复本 如let simpleObj = obj;
则只复本了 obj在栈上的操作符变量给 simpleObj 也就是说simpleObj实际存储的值是 obj的第一类的内存地址 对准与 obj同样的堆内存地址 所以改变 obj的值 simpleObj 的值也会改变
深复本 就是copy了这份第一类 放在另一块堆内存地址 改变之前的第一类 对这个复本的第一类不能有任何负面影响
js里有三种深复本形式
Object.assign方法实行的是浅复本,而并非深复本。也就是说,如果源第一类某个属性的值是第一类,那么目标第一类复本得到的是这个第一类的引用。
… 扩充和 assign 一样
JSON.parse(JSON.Stringify()) 深复本 但是缺点是不能复本 constructor 方法 解决办法就是递归