zoukankan      html  css  js  c++  java
  • 懵逼的闭包--for循环(转)

    <!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);
    }
    

      

  • 相关阅读:
    Code Forces 650 C Table Compression(并查集)
    Code Forces 645B Mischievous Mess Makers
    POJ 3735 Training little cats(矩阵快速幂)
    POJ 3233 Matrix Power Series(矩阵快速幂)
    PAT 1026 Table Tennis (30)
    ZOJ 3609 Modular Inverse
    Java实现 LeetCode 746 使用最小花费爬楼梯(递推)
    Java实现 LeetCode 745 前缀和后缀搜索(使用Hash代替字典树)
    Java实现 LeetCode 745 前缀和后缀搜索(使用Hash代替字典树)
    Java实现 LeetCode 745 前缀和后缀搜索(使用Hash代替字典树)
  • 原文地址:https://www.cnblogs.com/z-e-r-o/p/6141009.html
Copyright © 2011-2022 走看看