JavaScript - 闭包 - 实战运用 - 循环绑定事件详细解析

  • 闭包是一种机制,函数执行,产生一个不被释放的上下文,
    • 一是保护了上下文里面的私有变量不受外界干扰,
    • 二是私有变量的值也保存了下来,可以供其下级上下文调取使用,这种机制叫做闭包。
  • 闭包的弊端是会导致栈内存增加,项目中如果滥用闭包,会导致产品性能降低。

JS中获取的每一个DOM元素都是一个元素对象(堆内存),拥有很多的属性和方法;
实现元素点击事件行为:xxx.onclick = function(){...} ,就是给元素对象的私有属性onclick赋值;
当点击的时候, 浏览器监听到事件触发就会帮我们把赋值的函数执行。

经典案例

给每一个按钮的点击事件赋值打印当前按钮索引值事件。

错误代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>闭包</title>
</head>
<body>
    <input type="button" value="1111">
    <input type="button" value="2222">
    <input type="button" value="3333">
    <input type="button" value="4444">
	<script>
	    var btnList = document.querySelectorAll("input[type='button']");
	    console.log(btnList);
	    for(var i = 0;i < btnList.length; i++){ 
	        btnList[i].myIndex = i;              
	        btnList[i].onclick = function(){
	            console.log("当前索引是:"+ this.myIndex);
	        }
	    };
	</script>
</body>
</html>

依次点击按钮的结果显示都是4。
在这里插入图片描述
原因图形解析:
请添加图片描述

解决方法1:自定义属性方案

<!--...-->
<script>
var btnList = document.querySelectorAll("input[type='button']");
for(var i = 0;i < btnList.length; i++){
	btnList[i].myIndex = i;
	btnList[i].onclick = function(){
	    console.log("当前索引是:"+ this.myIndex);
	}
};
</script>
<!--...-->

依次点击按钮的结果:
在这里插入图片描述
图形解析:请添加图片描述

原理:

  • 在循环事件绑定的时候,给每一个元素对象设置一个自定义属性myIndex,存储元素的索引。
  • 事件触发的时候,this是点击的元素,所以基于元素.myIndex即可获取到元素的索引。

解决方法2:闭包

<!--...-->
<script>
var btnList = document.querySelectorAll("input[type='button']");
for(var i = 0;i < btnList.length; i++){ 
  (function(x){          
      btnList[x].onclick = function(){
          console.log("当前索引是:"+ x);
      }
  })(i)
};
</script>
<!--...-->

依次点击按钮的结果:在这里插入图片描述
图形解析:请添加图片描述
原理:利用了闭包的保护和保存机制

解决方法3:let

<!--... -->
<script>
var btnList = document.querySelectorAll("input[type='button']");
for(let i = 0;i < btnList.length; i++){ 
    btnList[i].onclick = function(){
        console.log("当前索引是:"+ i);
    }
};
</script>
<!--... -->

依次点击按钮的结果:在这里插入图片描述
原理:

  • 每一轮循环都有基于let声明的变量i ,所以循环体会查生一个私有的块级上下文。
  • i是私有的,分别存储着对应元素的索引值。
  • 函数/ 对象以外的大括号(循环/ 判断/ { } )中出现了以let/ const/ function/ class声明的方式,就会产生块级上下文。
  • var 既不会产生块级上下文,也不会受块级上下文影响。

解决方法4:事件的冒泡传播机制

<!--... -->
<input type="button" class="btn" index="0" value="1111">
    <input type="button" class="btn" index="1" value="2222">
    <input type="button" class="btn" index="2" value="3333">
    <input type="button" class="btn" index="3" value="4444">
    <script>
        document.onclick=function(ev){
        let target = ev.target,
            targetName = target.type;
            targetClass = target.className;
            if(targetName ==="button" && targetClass === "btn"){
                console.log("当前索引是:"+ target.getAttribute("index"));
            }
        }
    </script>
<!--... -->

依次点击按钮的结果:
在这里插入图片描述
原理:事件委托, 点击文档中的任意元素,都会触发document的点击行为(事件的冒泡机制)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值