<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
//面试经典问题: function onMyLoad(){
/*
抛出问题:
此题的目的是想每次点击对应目标时弹出对应的数字下标 0~4,但实际是无论点击哪个目标都会弹出数字5
*/
var arr = document.getElementsByTagName("p");
for(var i = 0; i < arr.length;i++){
arr[i].onclick = function(){
alert(i);
}
}
}
</script>
</head>
<body onload="onMyLoad()">
<p>产品一</p>
<p>产品二</p>
<p>产品三</p>
<p>产品四</p>
<p>产品五</p>
</body>
</html>

  本来以为只是个小循环,没想到一下掉坑里了.

搜索良久,,对闭包还是理解不了,,暂时找到几种方法算好理解的:

one:

/*
解决思路:
增加若干个对应的闭包域空间(这里采用的是匿名函数),专门用来存储原先需要引用的内容(下标),不过只限于基本类型(基本类型值传递,对象类型引用传递)
*/
for(var i = 0;i<arr.length;i++){ //声明一个匿名函数,若传进来的是基本类型则为值传递,故不会对实参产生影响,
//该函数对象有一个本地私有变量arg(形参) ,该函数的 function scope 的 closure 对象属性有两个引用,一个是 arr,一个是 i
//尽管引用 i 的值随外部改变 ,但本地私有变量(形参) arg 不会受影响,其值在一开始被调用的时候就决定了.
(function (arg) {
arr[i].onclick = function () { //onclick函数实例的 function scope 的 closure 对象属性有一个引用 arg,
alert(arg); //只要 外部空间的 arg 不变,这里的引用值当然不会改变
}
})(i); //立刻执行该匿名函数,传递下标 i(实参)
}

  two:

/*
解决思路:
将下标作为对象属性(name:"i",value:i的值)添加到每个数组项(p对象)中
*/
for(var i = 0;i<arr.length;i++){
//为当前数组项即当前 p 对象添加一个名为 i 的属性,值为循环体的 i 变量的值,
//此时当前 p 对象的 i 属性并不是对循环体的 i 变量的引用,而是一个独立p 对象的属性,属性值在声明的时候就确定了
//(基本类型的值都是存在栈中的,当有一个基本类型变量声明其等于另一个基本变量时,此时并不是两个基本类型变量都指向一个值,而是各自有各自的值,但值是相等的)
arr[i].i = i;
arr[i].onclick = function () {
alert(this.i);
}
}

  three:

/*
解决思路:
与解决办法一有点相似但却有点不太相似.
相似点:同样是增加若干个对应的闭包域空间用来存储下标
不同点:解决办法一是在新增的匿名闭包空间内完成事件的绑定,而此例是将事件绑定在新增的匿名函数返回的函数上 此时绑定的函数中的 function scope 中的 closure 对象的 引用 arg 是指向将其返回的匿名函数的私有变量 arg
*/
for(var i = 0; i<arr.length;i++){
arr[i].onclick = (function(arg){
return function () {
alert(arg);
}
})(i);
}

  

懵逼的闭包--for循环(转)的更多相关文章

  1. swift中闭包的循环引用

    首先我们先创造一个循环引用 var nameB:(()->())? override func viewDidLoad() { super.viewDidLoad() let bu = UIBu ...

  2. 前端(十三)—— JavaScript高级:回调函数、闭包、循环绑定、面向对象、定时器

    回调函数.闭包.循环绑定.面向对象.定时器 一.函数高级 1.函数回调 // 回调函数 function callback(data) {} // 逻辑函数 function func(callbac ...

  3. Swift 闭包使用(循环引用...)

    class networkTool: NSObject { //定义一个可选类型的闭包,用小括号()?括起闭包 var finishedCallBack2:((_ jsonData:String)-& ...

  4. JS闭包导致循环给按钮添加事件时总是执行最后一个

    加入如下脚本代码: <script> var list_obj = document.getElementsByTagName('li'); for (var i = 0; i <= ...

  5. 闭包 (循环事件获取不到i) 和 各种解决循环获取不到i的解决方法

    for(var i in fav){ (function(){                var p=i;                var obj=$S.getId(fav[i]);     ...

  6. Xcode8的调试技能Memory Graph 实战解决闭包引用循环问题

    Xcode8的调试技能又增加了一个黑科技:Memory Graph.简单的说就是可以在运行时将内存中的对象生成一张图. 那么通过一个实际项目来练习一下吧. 首先我们写了一个自定义UIView:MyVi ...

  7. JS高阶---闭包(循环遍历+监听)

    大纲: 主体: (1)场景1:点击按钮显示点击的第几个 注意:伪数组每次循环时都会重新计算一次长度,所以最好提出去或者直接加到for循环内部 结果: 分析: 1.i为全局变量 解决方案: 1.下标法 ...

  8. js闭包for循环总是只执行最后一个值得解决方法

    <style> li{ list-style: none;width:40px;height: 40px;text-align:center;line-height: 40px;curso ...

  9. Js闭包与循环

    目标:点击任何一个li,提示当前点击位置 <ul> <li>第1个</li> <li>第2个</li> <li>第3个</ ...

随机推荐

  1. linux命令总结

    vmstat: linux监控命令,可以展现服务器状态值. 一般vmstat工具的使用是通过两个数字参数来完成的,第一个是采样的时间间隔,单位是秒,第二参数是采样的次数 例:vmstat 3 2  ( ...

  2. Dedecms去掉URL中a目录的方法

    本文实例讲述了Dedecms去掉URL中a目录的方法.分享给大家,供大家参考.具体分析如下: 使用dedecms的朋友可能会发现自己的URL目录生成是会自动带有一个/A/目录了,那么要如何去掉URL中 ...

  3. Android开发:关于WebView

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://liangruijun.blog.51cto.com/3061169/647456 ...

  4. 修改Windows/Ubuntu/Mint多系统的默认启动顺序

    打开该配置文件 sudo gedit /etc/default/grub 其中的“GRUB_DEFAULT=0”就是设置的默认启动项了.GRUB启动项是按照启动菜单依次使用数字进行索引了,起始数字为0 ...

  5. BZOJ 3781: 小B的询问

    3781: 小B的询问 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 643  Solved: 435[Submit][Status][Discuss ...

  6. git版本控制?

    git是一个分布式的版本控制系统,版本控制系统,类似于保险箱,而我们的代码就是资产:通过对代码的有效管理可以更好的提高我们的生产效率:maven是主要是一个项目构建工具,解决的是我们个人在开发过程中的 ...

  7. mysql安装和配置

    一.下载mysql mysql下载页 我用的是5.6,点击旁边的"Looking for previous GA versions?"按钮就能看到5.6版本 mysql-5.6.3 ...

  8. 配置linux----------------ip

    在终端中输入 vi /etc/sysconfig/network-scripts/ifcfg-eth0 =================================== DEVICE=" ...

  9. ubuntu sudo update与upgrade的作用及区别

    ubuntu sudo update与upgrade的作用及区别 入门linux的同志,刚开始最迫切想知道的,大概一个是中文输入法,另一个就是怎么安装软件.本文主要讲一下LINUX安装软件方面的特点. ...

  10. Java编程中“为了性能”需做的26件事

    1.尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: (1)控制资源的使用,通过线程同步来控制 ...