前两天在用vuejs给公司网站写东西的时候,需要对数组进行赋值,然后就发现了个奇怪的现象,赋值后的数组会随着之前给它赋值的数组的变化而变化,然后就不淡定了,意识到可能是等号直接把内存指向也一并赋值了,所以,这个赋值遇到数组和对象的时候,一定要三思,我就查了下,并且记录一下,希望以后不会犯这种错误。
傻傻分不清楚的赋值
demo1
1 | var one = "girl"; |
大家猜猜结果吧,结果two没变,还是个”girl”。
demo2
1 | var one = {sex:"girl"}; |
哇塞,结果two也是没变,还是个”girl”。
demo3
1 | var one = {sex:"girl"}; |
完了,变了,变成”boy”了。
demo4
1 | var one = [{sex:"girl"}]; |
没有变哦,跟上面的demo2很像。
demo5
1 | var one = [{sex:"girl"}]; |
数组也是幸免不了的变了,跟上面的demo3很像。
原理
ECMAScript的变量值类型分为两种:
基本类型-包括Undefined, Null, Boolean, Number和String
引用类型-保存在内存中的对象们,不能直接操作,只能通过保存在变量中的地址引用对其进行操作
变量赋值时总是会copy一份的,如果是基本类型,copy的就是实际的值,如果是引用类型,copy的是指向Object的地址值,所以指向的还是同一个Object。
但是上例中的demo2和demo4是没变的,为啥呢,因为one又创建了一个新的地址空间,two指向的还是旧的one的地址空间,所以one没有改变。
1 | var a = "boy"; |
对于基本类型,比较的就是实际的值,而对于引用类型,比较的是地址值。
如何避免这种问题
避免的原理就是再创建一个新的对象,来避免重复的地址引用。
利用jQuery的$.extend()
1 | var x = { |
这时,无论x怎么改,y都是原来的x。
利用 JSON 全局对象
1 | var x = { |
对于数组
利用数组的splice方法
1 | var a = [1,2,3,4,5]; |
利用数组的map方法
1 | var a = [1,2,3,4,5]; |