从一个基础Javascript面试题谈起

记得第一次面试前端工程师的时候,面试官出了一个机试题,要求每个p单击时弹出不同的值,我是这么写的,执行的时候发现每次都是alert(5),当时坚持认为我的代码没有任何问题,心想这么简单的功能我怎么会弄错。时至今日,想起这件事,便写篇博文总结之。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>面试试题</title>
<script type="text/javascript">
function init() {
var pArr = document.getElementsByTagName("p");
for( var i=0; i<pArr.length; i++ ) {
pArr[i].onclick = function() {
alert(i);
}
}
}
</script>
</head>
<body onload="init();">
<p>段落1</p>
<p>断落</p>
<p>段落3</p>
<p>段落4</p>
<p>段落5</p>
</body>
</html>

执行以上的代码,会发现一个有趣的现象,每次单击p时弹出的结果都是5,究竟为什么呢,而不是0,1,2,3,4?我想发表一下个人见解:

以上代码是在onload的时候执行了init方法,即已经为每个P添加了单击事件监听,当我们单击P时,其实i的值此时已经是5了(这其实是一个程序执行的时间问题,在我们单击P之前,循环已经执行完毕,i的值最后变成了5退出了循环,如果我们可以做到在一个p添加单击时间之后和下一个p添加单击事件之前单击p的话,肯定得到的是0,1,2,3,4这样的结果,但是我们的速度不可能超过程序执行的速度,所以循环执行完后,i其实最后是5了,我们以后的单击都会alert(5),不知各位看官理解了没有)。

如果我们想每次单击都alert不同的值,我们可以参考下面这个简单可行的方法:

1
2
3
4
5
6
7
8
9
function init() {   
var pArr = document.getElementsByTagName("p");
for( var i=0; i<pArr.length; i++ ) {
pArr[i].i=i;
pArr[i].onclick = function() {
alert(this.i);
}
}
}

我们可以在循环添加单击事件时,将i的值存放到p里面(因为p是一个DOM对象,既然是对象,就可以添加属性和方法,这里我们为p添加一个属性i,赋值为i),最后我们每次单击p的时候alert的总是p[i]的属性值。

Ravior wechat
微信公众号:万物为媒, 关注一个技术人员的成长之路
写的不错, 点个赞吧!