--- 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 %}

现在问题就解决了!