实现点击任何一个li标签、可以弹出对应的index值
也可以应用于没有计时器的轮播图中
在写代码的过程中,碰到了一系列的问题:
- 在点击li标签之后,弹出的index是最后一个索引值
- var 和 let 的区别
问题与代码如下:
var ali=document.getElementsByTagName("li");
for(let i=0;i<ali.length;i++)
{
ali[i].index=i;
ali[i].onclick = function () {
alert(ali[i].index); //依次点击 弹出0,1,2,3,4
}
}
for(var j= 0;j<ali.length;j++)
{
ali[j].index=j;
ali[j].onclick = function () {
/*alert(ali[j].index); */ //单写出这一句会报错
alert(this.index); //依次点击 弹出0,1,2,3,4
}
}
/*
* 问题:
* 1、第一处注释处:为什么可以正确弹出0,1,2,3,4。且不需要改成alert(this.index);
* 2、第二处注释处:为什么单写这一句会报错?
* 3、第三处注释:为什么在这个for循环内必须要使用this.index,才可以弹出正确的0,1,2,3,4
* */
问题的解决
第一个问题 :就联系到了var 和 let 的区别
let:是ECMASscript 6 新增加的内容,let声明的变量只在声明的代码区块中可以使用。且不可以重复定义相同的变量。
var a;
let b;
console.log(a); //undefined
console.lig(b); //undefined
let b;//报错、不可以重复定义
在这里可以知道,在let和var声明的变量,未初始化,输出都是undefine
并且let不可以重复定义
console.log(a);//undefined
console.log(b);//ReferenceError: Cannot access 'b' before initialization
var a=10;
let b=9;
//在上面的两句console.log()被注释后
console.log(a);//10
console.log(b);//9
这段代码可以知道:
1.var声明的变量,对于JS来说会提前到整个代码的最前面,但是不会把初始值提前
2. let声明的变量,在没有被声明前输出会报错:Cannot access ‘b’ before initialization 意思是:不能在b的声明之前使用b。可知:let变量,不会被JS自动提前
var b=0;
for(let a=0;a<10;a++)
{
b+=a;
}
console.log(a);//ReferenceError: a is not defined
//在console.log(a);被注释之后
for (var i=0;i<10;i++){
b+=i;
}
console.log(i);//10
由这段代码可知:
- let变量,有局部作用域。把a在for循环中封锁起来
- var变量,全局作用域。没有区域作用域之说(除了在函数中)
现在可以解释问题1
-
由于每一次的for循环,i的值都在不断的更新。而JS引擎内部会记住上一次循环的值。当更新时,会在上一轮的基础上更改。
-
所以每一个ali[i].index=i; 都已经初始化了。从而可以正确的输出。
问题2 可以 和 问题3 一起解决
1、在JS 中,对于变量的声明。如果在函数内部没有找到变量的声明和定义,会是由内而外的找声明和定义。
var a=0;
function f() {
console.log(a);
}
f();//0
//由于在函数 f 内没有找到 a 的定义,就会往外找
//发现外部有var a=0;
//从而函数内部的a就为0
所以在问题2中,由于事件函数中没有找到 j 的声明或者定义,会自动的在外层找。发现了for循环中定义了 var j = 0.然而这时,for循环已经结束,j = ali.length .很明显的会报错。因为数组的最后一个元素下标为ali.length-1.所以alert(ali[j].index); 数组越界
问题3:this,只有在函数被调用的时候,才能确定this的指向。在这里this指向的就是任何一个被点击了的li标签。
this:所在的函数在那个对象中究指向这个对象。this在定时器中是特例。在事件函数中。this指向事件源。
所以可以弹出对应正确的index值