使用对象数组时碰到的问题
发现问题
昨天在搭建一个博客时,碰到这样一个问题:
有如下这样一个页面。可以看到,页面中有多个 a 标签。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
<body>
<a href="https://imgchr.com/i/ioWnL4"></a>
<a href="https://imgchr.com/i/ioWmyF"></a>
<a href="https://imgchr.com/i/ioWeQU"></a>
<a href="https://imgchr.com/i/ioWVzT"></a>
<a href="https://imgchr.com/i/ioBqIS"></a>
</body>
</html>
我的需求是:拿到所有 <a> 的 href 属性,并存入数组里。
我的 JS 代码如下:
var a = document.getElementsByTagName('a');
var result = [];
var obj = {};
for (var i = 0; i < a.length; i++) {
obj.href = a[i].href;
result.push(obj);
}
console.log(result);
这段代码看上去没有什么问题,那么我们来看一下输入结果呢。

可以看到,我们数组里面所有的值,均为最后一个 <a> 的 href 值。
奇怪!我们不是每次都给 obj.href 重新赋值了吗,为什么会是这个结果?
经过我的深思熟虑(没错…想了很久),终于想清楚为什么会是这种错误结果了。所以我决定写下来提醒自己,避免以后再犯这种错。
找到原因
JS 中数据类型分“基本类型”和“引用类型”两种。
基本类型的值就存在变量的地址里。而对于引用类型,其变量名是一个指针,指向的是存储这个变量的值的地址。
Object (对象)为引用类型,所以上面代码中的 obj 指向了一个地址,这个地址里保存了我们为 obj 所赋的值。由于 obj 这个地址一直没有发生改变,所以我们给数组 push 进去的所有元素,都指向了同一个地址,而由于每次赋值操作,使得后来的值覆盖了原先的值,导致所有的值都变成了最后一次所赋的值。
解决问题
问题找到了,那么我们怎么解决呢?答案很简单,只需这样修改代码:
var a = document.getElementsByTagName('a');
var result = [];
var obj = {};
for (var i = 0; i < a.length; i++) {
obj = {}; // 在代码中加上这句
obj.href = a[i].href;
result.push(obj);
}
console.log(result);
在代码中新添加的一句,作用是:每次都为 obj 重新声明一片内存区域,使得每次赋值操作都是独立的,这样就不会出现值覆盖的情况了。
总结
这次出现这样的问题,是因为我对这方面的知识掌握的不够扎实,好在我之前有比较认真学习过这方面的知识,最终还是找到了原因。