希望可以实现点击哪个就打印出对应的顺序
<ul>
<li>第0个</li>
<li>第1个</li>
<li>第2个</li>
<li>第3个</li>
<li>第4个</li>
</ul>
错误实现:
注意此处使用的var i=0, var是可以被重复定义的,最后执行了i++,根据垃圾回收机制,当点击事件发生的时候,i已经变成5了,所以不管点击哪个li,打印的都是5
window.onload=()=>{
const list = document.querySelectorAll('li')
for (var i=0; i<list.length; i++){
list[i].onclick = ()=>{
console.log(i)
}
}
}
正确实现:
方法一:给每个li添加自定义属性
window.onload=()=>{
const list = document.querySelectorAll('li')
for (var i=0; i<list.length; i++){
list[i].index = i
list[i].onclick = function (){
console.log(this.index)
}
}
}
方法二:自执行函数,并利用作用域的关系,定义函数把i传进来,并进行自动调用
for (var i=0; i<list.length; i++){
// (function(i){})表示定义,i表示形参;(i)表示调用,i表示实参
(function(i){
list[i].onclick = function(){
console.log(i)
}
})(i)
}
方法三:ES6中的let,let应用于块级作用域,块级作用域以大括号划分
let不会被垃圾回收机制回收,var为什么会被回收?因为var声明的变量会被覆盖,而let不能被覆盖,就会被存下来。
for (let i=0; i<list.length; i++){
list[i].onclick = ()=>{
console.log(i)
}
}
方法四:利用for循环的方法:filter、forEach、map(注意全都是ES5的,不是ES6的)
// 注意此处有一个兼容性问题,li是类数组,兼容性好的浏览器可以直接使用这三个方法,但是兼容性不好的不能直接用
// 为保证稳妥,最好转成真正的数组
const newArr = [].slice.call(list) // 或者const newArr = Array.prototype.slice.call(list), []是Array的原型
console.log(list) // NodeList(5) [li, li, li, li, li] NodeList是dom中的一个对象
console.log(newArr) // [li, li, li, li, li] 被转成了真正的数组
newArr.forEach((value,index)=>{
value.onclick=function(){
console.log(index)
}
})
newArr.filter((value,index)=>{
value.onclick=function(){
console.log(index)
}
})
newArr.map((value,index)=>{
value.onclick=function(){
console.log(index)
}
})
方法五:ES6中给Array的from方法
Array.from(list, function(value, index){
value.onclick=function(){
console.log(index)
}
})
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。