js循环添加onclick事件
来源:互联网 发布:算法导论 22.3 10 编辑:程序博客网 时间:2024/05/17 16:44
javascript在循环添加onclick事件时会出现函数传入参数均为最后一个值的问题,编写一个test.html如下所示:
<!doctype html><html lang="en"><head></head><body><input type='button' id='bt0' name='name1' value='0'/><input type='button' id='bt1' name='name2' value='1'/></body><script type='text/javascript'>for (var i=0;i<2 ;i++){var bt=document.getElementById('bt'+i);bt.onclick=function(){ console.log(i);//无论点击哪个按钮均打印2 };}</script></html>
了解javascript作用域机制的话。很容易看出问题出在哪里。循环结束后,i的作用域为windowscope,或者说i是全局变量,其值为2,click事件触发时显示的自然是2了。
为了解决这个问题,我们从onclick细细讲起
1.当我们点击一个button时,我们做了什么
让我们看看MDN中对onclick的解释
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick
首先,onclick是button的一个属性,我们给这个属性赋值一个函数指针(function pointer),就完成了一个事件绑定,当click事件触发时就会进入这个function。
其次,这个函数指针到底是什么呢?再看看MDN中对onclick后面的function的解释
可以看到这个function既可以是函数声明,也可以是函数表达式。所谓函数表达式和函数声明的区别,举个栗子:var example=function(){}是函数表达式,function example(){}是函数声明。所以这个function有以下三种形式,我们通常用的第一种形式,即匿名函数形式,实际上是一个匿名的函数表达式。
document.getElementById('bt0').click=function(){ //匿名函数 console.log('example0');}var example1=function(){ //函数表达式 console.log('example1');};document.getElementById('bt1').click=example1;function example2(){ //函数声明 console.log('example2');}document.getElementById('bt2').click=example2;
这是没有参数传递的情况,若有参数呢?直接在函数指针里加参数?elemtent.onclick=example(parameter)的形式显然不行,因为这是调用函数了,会直接执行。但是可以在example()函数内部返回一个function。
2.在函数表达式或函数声明中返回一个function
点击button后,调用元素对应的onclick事件,解析程序在匿名函数内部找不到i,转而找到外部作用域的i,即为2,所以打印出2。归根到底,是由于element.onclick=function(){}等式右边的匿名函数无法传参而无法维护自己的作用域。(别想element.onclick=function(i){}这样传参,因为onclick事件默认的参数是event)。那么解决方法也就很容易想到了,不用匿名函数,而是以函数表达式或函数声明的形式传递参数,这就需要在函数内部返回一个function。
var clickEventExpression=function(arg){return function(){console.log(arg);}};function clickEventDeclaration(arg){return function(){console.log(arg);}}for (var i=0;i<2 ;i++){var bt=document.getElementById('bt'+i);bt.onclick=clickEventExpression(i);//or bt.onclick=clickEventDeclaration(i)}
3.闭包
或者换个思路,仍用匿名函数,不过要在匿名函数内部产生一个可以自己维护的作用域,来保存变量i。咦,好熟悉的概念,这不就是闭包嘛。
“闭包就是将所有自由变量和函数绑定在一个封闭的表达式中,这个表达式可以保留在自由变量和函数创建之外的词法作用域。”这里我们用(function{})()形式的立即执行函数来创建一个封闭的表达式。
//加一层闭包,i 以局部变量形式传递给内层函数for (var i=0;i<2 ;i++){ (function(){ var bt=document.getElementById('bt'+i);var temp=i; bt.onclick=function(e){ console.log(temp); } })();}
或者
//加一层闭包,i以函数参数形式传递给内层函数for (var i=0;i<2 ;i++){ var bt=document.getElementById('bt'+i); bt.onclick=(function(arg){ return function(){ console.log(arg); }; })(i);}
4.let 和const
let和const的声明可以产生块级作用域,同样可以解决我们的问题。
for (var i=0;i<2 ;i++){let ii=i;//const也可以,块级作用域var bt=document.getElementById('bt'+ii);bt.onclick=function(){console.log(ii);};}
1 0
- js循环添加onclick事件
- js循环添加onClick事件--js的闭包
- js 循环添加点击事件
- js给网页中所有p元素添加onclick事件
- JS更改onclick事件
- JS ONCLICK常用事件
- JS onclick常用事件
- JS ONCLICK常用事件
- js的onclick事件
- 原生js onclick事件
- js中添加onclick
- 为TextBox添加onclick事件
- 为iframe添加onclick事件
- 给 iframe 添加 onclick 事件
- jquery 动态添加onclick事件
- 给按钮添加onClick事件
- 给超链接添加onclick事件
- 为iframe添加onclick事件
- 【JavaScript】DOM(一)基本概念和节点
- Exception
- jQuery的$().text(),用法
- python switch语句的多种实现方法
- Swift基础之自定义PUSH和POP跳转动画
- js循环添加onclick事件
- 机器学习数据来源总结(不断积累更新)
- unity3D-游戏/AR/VR在线就业班 蓝鸥C#入门字典学习笔记
- 8面向对象高级--->@property
- adb logcat常用命令小结
- Python之队列queue模块使用 常见问题与用法
- [C语言][LeetCode][232]Implement Queue using Stacks
- AS400 DB2 SQL常用函数总结
- LeetCode - Validate Binary Search Tree