JavaScript闭包 循环输出i
html
<body>
<p>产品一</p>
<p>产品二</p>
<p>产品三</p>
<p>产品四</p>
<p>产品五</p>
</body>
js
function init() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = function() {
alert(i);
}
}
}
window.onload = init;
上面代码点击每个p,输出都是5,因为这里的 i 是个引用。演示地址
要想输出对应的i,有以下方法:
1、将变量 i 保存给在每个段落对象(p)上
function init() {
var pAry = document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
pAry[i].i = i;
pAry[i].onclick = function() {
alert(this.i);
}
}
}
window.onload = init;
2、将变量 i 保存在匿名函数自身
function init() {
var pAry = document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
(pAry[i].onclick = function() {
alert(arguments.callee.i);
}).i = i;
}
}
window.onload = init;
caller返回一个函数的引用,这个函数调用了当前的函数;
callee返回正在执行的函数本身的引用,它是arguments的一个属性
3.加一层闭包,i以函数参数形式传递给内层函数
function init() {
var pAry = document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
(function(arg) {
pAry[i].onclick = function() {
alert(arg);
};
})(i); //调用时参数
}
}
window.onload = init;
4、加一层闭包,i以局部变量形式传递给内存函数
function init() {
var pAry = document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
(function() {
var temp = i; //调用时局部变量
pAry[i].onclick = function() {
alert(temp);
}
})();
}
}
window.onload = init;
5、加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)
function init() {
var pAry = document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
pAry[i].onclick = function(arg) {
return function() { //返回一个函数
alert(arg);
}
}(i);
}
}
window.onload = init;
6、用Function实现,实际上每产生一个函数实例就会产生一个闭包
function init() {
var pAry = document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
pAry[i].onclick = new Function("alert(" + i + ");"); //new一次就产生一个函数实例
}
}
window.onload = init;
7、用Function实现,注意与6的区别
function init() {
var pAry = document.getElementsByTagName("p");
for (var i = 0; i < pAry.length; i++) {
pAry[i].onclick = Function('alert(' + i + ')')
}
}
window.onload = init;
看了这篇文章,又想到用es5,es6的两个方法:
8、用es5 forEach函数
这里用forEach也行成了一个所谓的闭包,forEach里的执行函数也行成了一个闭包,每个执行体里,index都是一局部作用域,那为什么用Array.from呢,我们也可以用[].slice.call(node)我们类数组对象转化成真正的数组
function init() {
var pAry = document.getElementsByTagName("p");
//pAry = Array.from(pAry);
pAry = Array.prototype.slice.call(pAry);
pAry.forEach(function(currentItem,index){
currentItem.onclick = function(){
alert(index);
}
})
}
window.onload = init;
9、用es6的let声明块级变量
function init() {
var pAry = document.getElementsByTagName("p");
for( let i=0; i<pAry.length; i++ ) {
pAry[i].onclick = function() {
alert(i);
}
}
}
window.onload = init;
知乎关于这个问题也有一些回答
https://www.zhihu.com/question/33468703
JavaScript闭包 循环输出i的更多相关文章
- JavaScript利用闭包循环绑定事件
我们经常在做前端面试题的时候,会遇到循环绑定事件后,输出打印结果,很多人总是搞不清楚,今天借此机会跟大家梳理一下闭包相关作用. 1.首先我们举一个简单的例子. html部分: <a href=& ...
- 从javascript的循环问题来看待闭包本质
第一次接触这个问题还是在我刚开始学js的时候,当时就是一头雾水,时隔一年多了,突然又想起了这个问题,在这个春气盎然的周末,我就坐下来研究下并把结果和大家分享下: 先看代码:demo.html < ...
- JavaScript学习笔记-循环输出菱形,并可菱形自定义大小
var Cen = 6;//定义菱形中部为第几行(起始值为0) //for循环输出菱形 document.write("<button onclick='xh()'>点我for循 ...
- JavaScript闭包深入解析
for (var i=1; i<=5; i++) { setTimeout( function timer() { console.log( i ); }, i*1000 ); } --上面这段 ...
- JavaScript 闭包系列二(匿名函数及函数的闭包)
一. 匿名函数 1. 函数的定义,可分为三种 1) 函数声明方式 function double(x) { return 2*x; } 2)Function构造函数,把参数列表和函数体都作为字 ...
- JavaScript闭包模型
JavaScript闭包模型 ----- [原创翻译]2016-09-01 09:32:22 < 一> 闭包并不神秘 本文利用JavaScript代码来阐述闭包,目的是为了使普通 ...
- JavaScript 闭包整合
初遇闭包感觉很困惑,上网查看了些许介绍,有很多没看懂,就想先对能懂的东西整整 首先觉得要了解闭包,要先对一.JavaScript的变量作用域和作用域链有基本了解 1.变量的作用域分为:全局变量和局部变 ...
- JavaScript ——闭包理解
昨天晚上听别人谈起闭包这个东西,虽然对js有一点了解但却丝毫没有印象,今天也没什么事就顺便研究了一下满足好奇宝宝.整合于网上的理解,记录一下. 一.闭包的作用域 要理解闭包,首先必须理解Javascr ...
- Javascript闭包的一些研究
原文:Javascript闭包的一些研究 本文不谈闭包的概念,因为概念容易把人搞晕,本文希望通过几个鲜活的例子来探究闭包的性质,相信对理解闭包会有所帮助. 程序1 var f = (function( ...
随机推荐
- 多线程并发测试(apache ad)
1.配置 ThreadPoolTaskExecutor bean <?xml version="1.0" encoding="UTF-8"?> ...
- HDU1505-City Game(记忆化搜索)
City Game http://acm.hdu.edu.cn/showproblem.php?pid=1505 Problem Description Bob is a strategy game ...
- python之时间处理time模块
import time import datetime ''' print(time.time()) #返回当前系统时间戳 print(time.ctime()) #返回当前系统时间 print(ti ...
- android静默安装和智能安装(转)
Android 静默安装和智能安装的实现方法 http://blog.csdn.net/fuchaosz/article/details/51852442 Android静默安装实现方案,仿360手机 ...
- D3DXCreateTexture
HRESULT D3DXCreateTexture( __in LPDIRECT3DDEVICE9 pDevice, __in UINT Width, __in UINT Height, __in U ...
- 常用Style
有些输入框什么的,字数限制什么的style,ceb为我们写好了.我感觉,每个app的style都是很有用的一个东西. <?xml version="1.0" encoding ...
- SXCPC2018 nucoj1999 占领城市
#include <iostream> #include <cstring> #include <cstdio> #include <queue> us ...
- Leetcode 650.只有两个键的键盘
只有两个键的键盘 最初在一个记事本上只有一个字符 'A'.你每次可以对这个记事本进行两种操作: Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的). Past ...
- nyoj 题目5 Binary String Matching
Binary String Matching 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 Given two strings A and B, whose alp ...
- iOS设备唯一标识(可以用版)
由于UDID和OpenUDID被禁用,系统自带的的识别唯一标识有两种 广告标示符(IDFA-identifierForIdentifier) 这是iOS 6中另外一个新的方法,advertisingI ...