用纯 JS 实现点击一个列表时,输出对应的索引号?

面试题目:用纯 JS 实现点击一个列表时,输出对应的索引号?(不能使用 jQuery)

如何使用原生 Javascript 实现点击一个列表时,输出对应的索引号?

看到这个题目,我就知道了,面试官可能会考察一下对闭包的掌握。经验不足的小伙伴们可能会这样去实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
</div>
<script>
var dom = document.querySelectorAll('ul li');
for(var i=0,len=dom.length;i<len;i++){
dom[i].addEventListener('click',function(){
console.log(i);
},false)
}
</script>

当我们点击列表的时候,弹出的都是 6,这是怎么回事呢?
这是因为我们在使用了 var 声明的变量,是全局作用域,不是块级作用域。也就是说,for 循环 6 次,每次改变的都是同一个 i,所以它的值会从 0 一直加到 6。
还有一个问题就是闭包导致的,闭包保存的是外部变量的引用,而不是值。因此可以循环 6 次监听器创建 6 个闭包,它里面的 i 引用的是同一个,全部指向了 6。

方法一:使用ES6中的 let替代var

1
2
3
4
5
6
7
8
<script>
var dom = document.querySelectorAll('ul li');
for(let i=0,len=dom.length;i<len;i++){
dom[i].addEventListener('click',function(){
console.log(i);
},false)
}
</script>

let声明的变量支持的是块级作用域。

方法二:使用立即执行函数来判断闭包对外部变量i的引用

1
2
3
4
5
6
7
8
9
10
<script>
var dom = document.querySelectorAll('ul li');
for(var i=1,len = dom.length;i<len;i++){
(function(i){
dom[i].addEventListener('click',function(){
console.log(i);
},false)
})(i)
}
</script>

方法三:事件委托的方法

1
2
3
4
5
6
7
8
var ul = document.querySelector('ul');
var dom = document.querySelectorAll("ul li");
ul.addEventListener('click',function(e){
var target = e.target;
if(target.nodeName.toLowerCase() === 'li'){
console.log([].indexOf.call(dom,target));
}
},false);

这个方法使用了事件监听,减少了监听器的绑定。

文章目录
  1. 1. 如何使用原生 Javascript 实现点击一个列表时,输出对应的索引号?
  2. 2. 方法一:使用ES6中的 let替代var
  3. 3. 方法二:使用立即执行函数来判断闭包对外部变量i的引用
  4. 4. 方法三:事件委托的方法
本站访客数人次