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