JavaScript中子函数访问外部变量的方法
我们在写web页面时,肯定会经常遇到下面这种情况:
<body>
<div class="btns-wrapper"></div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var wrapper = $('.btns-wrapper');
for(var i = 0; i < 5; i++){
var btn = $('<button>按钮' + i + '</button>').appendTo(wrapper);
btn.on('click', function(evt){
console.log('点击按钮:' + i);
});
}
</script>
</body>
代码很简单,就是在页面上创建几个按钮,同时定义按钮的点击事件

可当点击按钮时,我们发现获取到的序号一直都是5,也就是 i 最后的值。
这是因为定义click事件时的匿名函数所引用的都是同一个变量 i
解决办法1:立即执行
var wrapper = $('.btns-wrapper');
for(var i = 0; i < 5; i++){
var btn = $('<button>按钮' + i + '</button>').appendTo(wrapper);
//默认方法
//btn.on('click', function(evt){
// console.log('点击按钮:' + i);
//});
//方法1:立即执行
btn.on('click', (function(n){
return function(evt){
console.log('点击按钮:' + n);
}
})(i));
}
这种方式就是在定义事件时直接为每个按钮都创建了一个独立的匿名函数(闭包),并且每个函数都持有正确的 i 变量
解决办法2:利用jquery的事件传参
var wrapper = $('.btns-wrapper');
for(var i = 0; i < 5; i++){
var btn = $('<button>按钮' + i + '</button>').appendTo(wrapper);
//默认方法
//btn.on('click', function(evt){
// console.log('点击按钮:' + i);
//});
//方法2:利用JQuery的事件传参
btn.on('click', { i: i }, function(evt){
console.log('点击按钮:' + evt.data.i);
});
}
这种办法就简单多了,直接利用jquery将参数体传递给匿名函数即可。
解决办法3:利用dom的data属性
var wrapper = $('.btns-wrapper');
for(var i = 0; i < 5; i++){
var btn = $('<button>按钮' + i + '</button>').appendTo(wrapper);
//默认方法
//btn.on('click', function(evt){
// console.log('点击按钮:' + i);
//});
//方法3:利用dom的data属性
btn.data('i', i);
btn.on('click', function(evt){
console.log('点击按钮:' + $(this).data('i'));
});
}
这种方法也很简单,弊端就是无法利用data属性定义结构化的数据。
综合来看,如果是jquery环境,利用事件参数来转递变量是最简单的,而且可以传递结构化的数据。
否则只能通过立即执行(闭包)的方式。
JavaScript中子函数访问外部变量的方法的更多相关文章
- ios中block访问外部变量的一些注意点
Block类型是一个C级别的语法和运行机制.它与标准的C函数类似,不同之处在于,它除了有可执行代码以外,它还包含了与堆.栈内存绑定的变量.因此,Block对象包含着一组状态数据,这些数据在程序执行时用 ...
- javascript中函数声明、变量声明以及变量赋值之间的关系与影响
javascript中函数声明.变量声明以及变量赋值之间的关系与影响 函数声明.变量声明以及变量赋值之间有以下几点共识: 1.所有的全局变量都是window的属性 2.函数声明被提升到范围作用域的顶端 ...
- Java 访问限制符 在同一包中或在不同包中:使用类创建对象的权限 & 对象访问成员变量与方法的权限 & 继承的权限 & 深入理解protected权限
一.实例成员与类成员 1. 当类的字节码被加载到内存, 类中类变量.类方法即被分配了相应内存空间.入口地址(所有对象共享). 2. 当该类创建对象后,类中实例变量被分配内存(不同对象的实例变量互不相同 ...
- awk内置函数、外部变量
外部变量 ①获取外部变量 格式: awk '{action}' 变量名=变量值 ,这样传入变量可以在action中获得值. 示例: test='awk test'--day-5 外部变量 ①获取外部变 ...
- PHP自定义函数使用外部变量
一般,php的自定义函数不能直接使用外部变量. 在php自定义函数中使用外部变量前,需要先使用global对外部变量进行声明. <?php $var = "hello World!& ...
- 关于Lambda表达式访问外部变量
在<C#高级编程>一书中提到通过Lambda表达式可以访问Lambda表达式块外部的变量 ,这是一个很好的功能(类似Js中的 闭包).但是如果没有正确的使用,会非常危险. 比如下面的事例中 ...
- Javascript中函数提升和变量提升
词法分析 词法分析方法: js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 具体步骤如下: 函数在运行的瞬间,生成一个活动对象(Active ...
- unittest之跳过用例(skip) (含如何调用类里面函数相互调取变量的方法)
当测试用例写完后,有些模块有改动时候,会影响到部分用例的执行,这个时候我们希望暂时跳过这些用例. 或者前面某个功能运行失败了,后面的几个用例是依赖于这个功能的用例,如果第一步就失败了,后面的用例也就没 ...
- mybatis:访问静态变量或方法
访问方法: <if test="@com.csget.constant.ConstantApp@getUser('mobile')== 'kf'"> <![CDA ...
随机推荐
- Codeforces Round #713 (Div. 3)AB题
Codeforces Round #713 (Div. 3) Editorial 记录一下自己写的前二题本人比较菜 A. Spy Detected! You are given an array a ...
- Rabbit MQ一些参数解释
//ConnectionFactory(连接工厂): 生产Connection的的工厂 //Connection(连接):是RabbitMQ的socket的长链接,它封装了socket协议相关部分逻辑 ...
- Visual Lab Online —— Beta版本发布声明
项目 内容 班级:北航2020春软件工程 博客园班级博客 作业:Beta阶段发布声明 发布声明 目录 发布方式.发布地址与运行环境要求 软件主体 浏览器扩展 Beta版本新功能 登录注册页 注册时邮箱 ...
- python介绍,计算机核心基础,与运行程序有关的三大核心硬件,操作系统
python介绍,计算机核心基础,与运行程序有关的三大核心硬件,操作系统 引子 python是什么? 什么是编程语言?为何要有编程语言? 什么是编程?什么是程序?什么是进程?为何要编程? 计算机基础 ...
- C#是怎么跑起来的
解释流程前,需要了解一些基本的概念. 基本概念解释: CPU :中央处理器,计算机的大脑,内部由数百万至数亿个晶体管组成,是解释和运行最终转换成机器语言(二进制代码)的地方.机器语言是通过CPU内存的 ...
- java基础——多维数组和稀疏数组
多维数组 多维数组可以堪称数组的数组,比如二维数组就是一个特殊的一维数组,其中每一个元素都是一个以为数组 而且数组 int a[][]= new int[2][3]; public class Arr ...
- Jmeter 设置中文
1.正常启动jmeter.bat 2.点击[Options]选项,弹出下拉菜单选择[Choose Language]选项3.选择[Choose Language]选项,弹出下一级菜单选择[Chines ...
- tail -fn 1000 test.log | grep '关键字' 按照时间段 sed -n '/2014-12-17 16:17:20/,/2014-12-17 16:17:36/p' test.log /var/log/wtmp 该日志文件永久记录每个用户登录、注销及系统的启动、停机的事件
Linux 6种日志查看方法,不会看日志会被鄙视的 2020-02-11阅读 7.3K0 作为一名后端程序员,和Linux打交道的地方很多,不会看Linux日志,非常容易受到来自同事和面试官的嘲讽 ...
- 单独跑ltp-20200508 ./runltp
# cat r3.sh#!/bin/bash # cat r3.sh#!/bin/bashi=1for ((; i<=1000; i++))do/opt/ltp/runltp -s fmtmsg ...
- mysql基础之mariadb对表中数据的增删改查
复习: 查看表:show tables; 创建表:create table 表名(字符类型); 删除表:drop table 表名; 对表的结构进行增删改查: 查看表结构:desc 表名; 修改表-添 ...