JavaScript数组赋值浅谈
开头,说明一下两个常用的概念:深拷贝和浅拷贝
1.浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”
1 let arr = [1,13,16,5,8]; 2 let newArr = arr; 3 newArr.sort((a,b)=>a-b); 4 console.log(arr) // [1,5,8,13,16]
显然,新数组newArr只是原数组arr的一个引用,在对newArr排序时,数组对象arr也被改变了。
如果想要不改变原数组,就需要用到深拷贝。代码如下:
1 let arr = [1,13,16,5,8]; 2 let newArr = new Array(arr); 3 newArr.sort((a,b)=>a-b); 4 console.log(newArr) // [1,5,8,13,16] 5 console.log(arr) // [1,13,16,5,8]
说到这里,似乎已经对js数组传递有了全面的了解,但是最近在知乎看到这样一段代码:
var a = [1,2,3]; var b = a; a = [4,5,6]; alert(b); //[1,2,3]
这样的结果就有点令人奇怪了,数组对象b既然是a的一个引用,那么改变a的同时,b理所应当发生变化呀。然而事实却是b并没有发生改变。
仔细深究,便可发现问题所在。关于JavaScript是按值传递还是按引用传递,推荐文章:https://zhuanlan.zhihu.com/p/24080761
首先需要说明无论是a还是b,其实都是数组实例 [1,2,3] 的引用吗,当把a赋值给b时,其实只是让b指向a所指向的数组实例。
因此,a=[4,5,6]不过是将a指向了新的数组实例,对b并没有什么影响。图解如下:
而之前谈到的数组排序,将arr的引用赋值给newArr之后,对newArr进行排序,实际上是通过引用地址,将原数组对象或者说原数组实例改变了,因此引用arr也发生了改变。
谈论至此,以上问题均可以合理解释。
此番论述为网上查阅他人的博客和见解,再结合自己的理解所得结论,如有不对,请指出。
2019-07-17
实践运用笔记
在vue中使用v-bind绑定js数组中的数据时,当使用数组下标(如:array[1] = 5)修改数组数据时,发现v-bind绑定的数组数据并未修改,而在控制台打印出数组,发现数组已经修改了。根据上述js数组特性,我猜测,通过数组下标修改仅仅修改了该数组的一个引用,而对数组实例并没有影响。测试:使用array对象的方法(如:splice)修改该数组,发现v-bind绑定的数组数据也修改了,这似乎证明了该结论。在本次实践中,我通过splice方法对指定位置进行元素替换。