For循环onclick事件闭包问题
ERROR:控制台会报出: is not defined
错误
问题描述 : 如果我们对于一组元素(相同的标签)同时进行onclick事件处理的时候(在需要获取到索引的时候),一般是写一个for循环,但是onclick是一个异步调用的,所以会带来一个问题,当我们触发这个事件的时候,我们能获取的i值是for完整执行完后i的值,而不能获取到代码顺序里i的值
以前惯用的解决方式
<script type="text/javascript">
window.onload = funtion(){
var lis = document.getElementsByTagName('li');
for( var i = 0; i < lis.length; i ++ ){
lis.index = i;
lis[i].onclick = function(){
console.log( this.index );
};
}
};
</script>
利用闭包解决(一)
增加若干个对应的闭包域空间(采用匿名函数实现)专门用来存储原先需要引用的内容(下标值),只限于基本类型(基本类型值传递,对象类型引用传递)
<script type="text/javascript">
for(var m =0 ; m< spanBtn.length ; m++){
!function(i){
spanBtn[i].onclick = function(){
for(var j =0 ; j<imgbox.length; j++)
imgbox[j].style.display = "none";
imgbox[i].style.display = "block";
}
}(m)
}
</script>
利用对象属性(二)
将下标作为对象属性(name:"i",value:i的值)添加到每个数组项(p对象)中
<script type="text/javascript">
for(var i=0; i<arr.length; i++){
//为当前数组项(当前p对象)添加一个名为i的属性,值为循环体i变量的值
//此时当前p对象的i属性并不是对循环体的i变量的引用,而是一个独立p对象的属性,属性值在声明的时候就确定了
arr[i].i = i;
arr[i].onclick = function (){
console.log(this.i);
}
}
</script>
匿名闭包空间(三)
增加若干个对应的闭包域空间用来存储下标 新增的匿名闭包空间内完成事件绑定(三)
//绑定的函数中的function scope中的closure对象的引用arg是指向将其返回的匿名函数的私有变量arg
<script type="text/javascript">
for(var i = 0; i<arr.length; i++){
arr[i].onclick = (function(arg){
return function () {
console.log(arg);
}
})(i);
}
</script>
使用ES6的let关键字(四)
"use strict";
var arr = document.getElementsByTagName("p");
for(var i = 0; i<arr.length; i++){
let j = i;//块级变量
arr[i].onclick = function () {
console.log(j);
}
}
知识点总结
1 . 要解决此问题,首先要了解闭包的概念。闭包是JavaScript语言的一个难点,也是它的特色,很多高级应用都要依靠它来实现。
[ 闭包概念 ]:简而言之,闭包就是能够读取其他函数内部变量的函数,由于在JavaScript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成定义在一个函数内部的函数。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
2 . 闭包的用途
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
3 . 使用闭包的注意点
[ 1 ] 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
[ 2 ] 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。