var a = [
{
name: 'is_empty',
items: ['1', '2', '3', '4', '5']
},
{
name: 'is_true',
items: ['6', '7', '8', '9', '10']
}
]
var b = []
for (var i = 0; i < a.length; i++) {
b[i] = a[i]
}
// 注释掉a[0] = [], 此时B 为{[], ['1', '2', '3', '4', '5']}
// 未注释掉的情况下,B为{[1, 2, 3, 4, 5]}, {[6, 7, 8, 9, 10]}
// a[0] = []
// console.log(b) // {['6', '7', '8', '9', '10']}, {['6', '7', '8', '9', '10']}
// a[0].items = []
// console.log(b) // {[], [6, 7, 8, 9, 10]}
重置a[0] = []
的时候,数组的引用被切断了,但是如果只重置a[0].items = []
时候,引用却并未被切断,这是为什么?
假设这有个数组[{},{}](就是你上面a引用的那个,我简写吧)
a是它的指针,指向这个数组所在的地址
然后你创建了一个变量b,把那个数组里面的元素地址放到了b里面,因为那个数组里面的元素是对象 所以b[i] = a[i]的操作也只是a[i]把某个地址赋值给了b[i]。他们都是一个指针。
下面进入分支:
a[0] = []的情况:a[0] 本来是一个指向[{},{}]其中一个元素的指针,后被替换成[]空数组的指针。然后给这个指针所指的对象(也就是空数组)添加了一个属性item,这个属性是一个空数组的指针。b还是指向[{},{}],没有任何影响。
a[0] = []被注释的情况:下一条语句 a[0].item = []。在这条语句执行前,a[0]还是和b[0]一样,是指向[{},{}]一个元素的指针。执行这条语句之后,也就是a[0]指向的这个对象的item属性被覆盖为一个空数组的指针。但是b[0]指向的内存地址还是没有变的,还是跟a[0]一样的。所以b[0].item也还是指向那一块内存,所以b[0].item = a[0].item = []。
(取属性的操作会对对象所在内存地址块执行操作,个人总结。。)
需要注意的地方就是 引用类型的赋值是把对象的地址传递给变量,让变量成为它的指针。所以a[0] = b[0] 都一样都指向[{},{}]的一个元素。或许你之前很有心的先var b = []开辟了一个内存。但是这个新的内存里面存放的东西,都是指向[{},{}]的指针。也就是通篇涉及到的有三个地址块。一个是存放a数组的地址,一个是存放b数组的地址,一个是[{},{}]的地址。
参考关键字:Call by sharing
附上例子希望能看懂:

欢迎指正,一起进步。刚刚开始接触可能描述不规范。