--- title: JavaScript中Array.push进去的是指针 labels: ["前端"] description: 说来惭愧,学前端到今天才发现这么一个问题。不求甚解,早晚会出问题的。 ---
说来惭愧,学前端到今天才发现这么一个问题。不求甚解,早晚会出问题的。
起因是,我写了大概如下的代码。
{% highlight javascript %} var numCol = [], temp = [1]; for(var i = 0; i < 2; i++){ numCol.push(temp); console.log(numCol); temp[0] = 4; } {% endhighlight %}Console.log的结果如下:
{% highlight console %} [ [1] ] [ [4], [4] ] {% endhighlight %}测试环境为Node v0.10.35。在Chrome下测试,发现console.log()出来的好像也是指针。
问题就是,array.push的是一个指针。接下来请看下面的对比样例:
{% highlight javascript %} var numCol = [], temp = [1]; for(var i = 0; i < 2; i++){ numCol.push(temp); console.log(numCol); temp = [4]; } {% endhighlight %}输出结果:
{% highlight console %} [ [1] ] [ [1], [4] ] {% endhighlight %}我们想要的结果出来了。之后就在想这个问题,如果换成对象的话,会怎么样呢?测试代码如下:
{% highlight javascript %} var numCol = [], temp = { "a": 'a' }; for(var i = 0; i < 2; i++){ numCol.push(temp); console.log(numCol); temp.a = 'b'; } {% endhighlight %}输出:
{% highlight console %} [ { a: 'a' } ] [ { a: 'b' }, { a: 'b' } ] {% endhighlight %}基本可以确定是指针的问题了,接下来用字符串测试,代码如下:
{% highlight javascript %} var numCol = [], temp = 'abc'; for(var i = 0; i < 2; i++){ numCol.push(temp); console.log(numCol); temp[0] = 'b'; } {% endhighlight %}输出:
{% highlight console %} ['abc'] ['abc', 'abc'] {% endhighlight %}并没有影响,应该说temp[0] = 'b'这句话形同虚设。
之后对字符串进行测试,发现temp[0]只有get功能,没有set功能。大家可以通过下面的例子理解。
{% highlight console %} > var a = 'abc' undefined > a[0] 'a' > a[0] = 'b' 'b' > a[0] 'a' {% endhighlight %}这样试下来,我上面说得意思是不是比较明确了?
那么如何去解决这个问题呢?先想的是两个数组不停相互赋值,看看可不可以?别急,在试验前先分析一下,看看我下面的测试:
{% highlight console %} > var a = [1, 2, 3] undefined > var b = a undefined > a[0] = 4 4 > b [ 4, 2, 3 ] {% endhighlight %}握了棵草。。。赋值传的也是指针啊,我突然见感受到了弱类型语音深深的恶意。但如果站在这个角度去看这个问题的话,其实这就是所谓的浅复制和深复制的问题。其实所谓浅复制,就是像这样,b = a实际上是让b也指向a,a变b也变,b变a也变;而深复制,就是让b具有a的内容,a变b不变,b变a不变。
之后就去查js里面解决深浅复制问题的方案了。对于数组,有两个现成的函数都可以处理,对象的话就要自己写代码遍历了。数组的解决方案也很简单,直接贴上解决后的代码。
方案一:slice()
{% highlight javascript %} var numCol = [], temp = [1]; for(var i = 0; i < 2; i++){ numCol.push(temp.slice(0)); console.log(numCol); temp[0] = 4; } {% endhighlight %}方案二:concat()
{% highlight javascript %} var numCol = [], temp = [1]; for(var i = 0; i < 2; i++){ numCol.push(temp.slice(0)); console.log(numCol); temp[0] = 4; } {% endhighlight %}现在问题就解决了!