JavaScript中重新赋值数组后原有引用失效是什么原因?
核心原理
JS 中引用类型(数组、对象等)的变量存储的不是值本身,而是该值在堆内存中的地址,你遇到的差异本质是修改原引用指向的内存内容和给变量重新赋值新的内存地址是完全无关的两个操作。
第一个示例拆解
let testArray = [1, [10, 11, 12], 3, 4, 5]; let testValue = testArray; testArray.push(13); testArray = [20, 21, 22]; console.log(testArray); // [20,21,22] console.log(testValue); // [1, [10,11,12], 3,4,5,13]
执行逻辑:
- 声明
testArray时,堆内存生成第一个数组(记为数组A),testArray存储的是数组A的内存地址 - 赋值
testValue = testArray时,是把数组A的地址复制给了testValue,两个变量此时指向同一个数组 - 执行
push操作时,是通过地址找到数组A,直接修改数组A的内容,所以两个变量指向的内容同步更新 - 执行
testArray = [20,21,22]时,堆内存生成了新的数组(记为数组B),只是把testArray存储的地址改成了数组B的地址,这个操作完全不会影响testValue,它依旧存储数组A的地址、指向数组A
第二个示例拆解
let testArray2 = [1, [10, 11, 12], 3, 4, 5]; let testValue2 = testArray2[1]; testArray2.push(13); testArray2[1] = [20, 21, 22]; console.log(testArray2); // [1, [20,21,22], 3,4,5,13] console.log(testValue2); // [10,11,12]
执行逻辑:
- 声明
testArray2时,堆内存生成外层数组(记为数组C)和内层子数组(记为数组D),数组C的第1位存储的是数组D的地址 - 赋值
testValue2 = testArray2[1]时,是把数组D的地址直接复制给了testValue2,testValue2直接指向数组D - 执行
testArray2[1] = [20,21,22]时,堆内存生成新的子数组(记为数组E),只是把数组C的第1位存储的地址改成了数组E的地址,这个操作只会修改数组C的内容,完全不会影响testValue2,它依旧存储数组D的地址、指向数组D
内容的提问来源于stack exchange,提问作者Static
相关产品推荐
相关产品推荐

