zoukankan      html  css  js  c++  java
  • JS闭包

    问题1:闭包

    考虑下面的代码:

    var nodes = document.getElementsByTagName('button');
    for (var i = 0; i < nodes.length; i++) {
       nodes[i].addEventListener('click', function() {
          console.log('You clicked element #' + i);
       });
    }

    请问,如果用户点击第一个和第四个按钮,控制台上会输出什么?为什么?

    答案

    上面代码的目的在于检测JavaScript的一个重要概念:闭包。对于每一个JavaScript开发者来说,如果你想在网页中编写5行以上的代码,那么准确理解和恰当使用闭包是非常重要的。如果你想开始学习或者只是想简单地温习一下闭包,那么我强烈建议你去阅读这个教程:Colin Ihrig 写的JavaScript Closures Demystified 。

    好了,回到上面的代码。控制台会输出两次You clicked element #NODES_LENGTH,其中#NODES_LENGTH等于nodes的结点个数。由于闭包中变量的值不是静态的,i的值并不是添加click事件处理器时的值(比如,当给第一个button添加click事件处理器时i为0,给第二个添加时i为1)。当for循环结束时,变量i的值等于nodes的长度。因此事件被执行时,控制台会输出变量i当前的值,即等于nodes的长度。

    问题2:闭包

    修复上题的问题,使得点击第一个按钮时输出0,点击第二个按钮时输出1。

    答案

    有多种办法解决这个问题,下面我给出其中的两种。

    第一个解决方案要用到一个IIFE来创建另外一个闭包,从而得到所希望的i的值。相应的代码如下:

    var nodes = document.getElementsByTagName('button');
    for (var i = 0; i < nodes.length; i++) {
       nodes[i].addEventListener('click', (function(i) {
          return function() {
             console.log('You clicked element #' + i);
          }
       })(i));
    }

    另一个解决方案不使用IIFE,而是将函数移到循环的外面,代码如下:

    function handlerWrapper(i) {
       return function() {
          console.log('You clicked element #' + i);
       }
    }
     
    var nodes = document.getElementsByTagName('button');
    for (var i = 0; i <nodes.length; i++) {
       nodes[i].addEventListener('click', handlerWrapper(i));
    }

    来源:http://web.jobbole.com/81785/

  • 相关阅读:
    魔术球问题
    【模板】网络最大流
    [SCOI2010]股票交易
    [SCOI2009]生日礼物
    [HAOI2007]修筑绿化带
    [HAOI2007]理想的正方形
    [USACO12MAR]花盆Flowerpot
    滑动窗口
    斐波那契公约数
    [SDOI2008]仪仗队
  • 原文地址:https://www.cnblogs.com/jack2013/p/4511680.html
Copyright © 2011-2022 走看看