zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    android 进程/线程管理(一)----消息机制的框架
    android的屏幕保持常亮
    android network develop(3)----Xml Parser
    android network develop(2)----network status check
    android network develop(1)----doing network background
    android 开发小记
    转 Android中shape中的属性大全
    转 Android学习 之 ColorStateList按钮文字变色
    《大话设计模式》c++实现 建造者模式
    《大话设计模式》c++实现 外观模式
  • 原文地址:https://www.cnblogs.com/fazero/p/6752771.html
Copyright © 2011-2022 走看看