pouta
V2EX  ›  问与答

一段 js 代码,不知道是什么问题

  •  
  •   pouta · Oct 31, 2016 · 2600 views
    This topic created in 3503 days ago, the information mentioned may be changed or developed.
    var page = document.getElementsByClassName('swiper-pagination-bullet');
    
    for(var i = 0;i<page.length;i++){
    
      page[i].innerHTML = i+1;
      
      page[i].addEventListener('click',function(){
      
       	 alert(i);	//为什么这里 i 的值都等于 page.length
         
    });
    
    }
    
    15 replies    2016-10-31 17:04:22 +08:00
    ycycwx
        1
    ycycwx  
       Oct 31, 2016 via iPhone
    好经典的面试题...
    mlkr
        2
    mlkr  
       Oct 31, 2016 via Android
    var 作用域的问题 ,换成 let 试试
    clearbug
        3
    clearbug  
       Oct 31, 2016 via Android
    好经典的面试题。。。你需要去看看闭包
    pouta
        4
    pouta  
    OP
       Oct 31, 2016
    @ycycwx 不是面试题 是我自己写的时候 遇到的坑
    wubotao
        5
    wubotao  
       Oct 31, 2016
    因为执行点击事件时, i 的值已经变成了 page.length
    i 不是取运行时的值,而是取 for 循环完成之后的值
    wubotao
        6
    wubotao  
       Oct 31, 2016
    @mlkr 不是作用域的问题,是代码执行顺序的问题。
    Sunyanzi
        7
    Sunyanzi  
       Oct 31, 2016
    萌新你好 ... 槽点太多其实不太知道该从何说起 ... 我试试看用最简单的方法跟你解释下吧 ...

    JavaScript 是一门只有「函数作用域」而没有「块级作用域」的语言 ...

    你的变量也好闭包也罢 ... 只要它们是被定义在同一个函数里的 ... 就会始终各自指向同样的地址 ...

    解决方法也很简单 ... 另开一个域就好 ... 方法如下 ...

    page[i].addEventListener('click',( function( i ) {
    return function() {
    alert(i); // 这样就不会相等啦
    }
    } )( i );
    Sunyanzi
        8
    Sunyanzi  
       Oct 31, 2016   ❤️ 1
    一言以蔽之 ... 你的做法虽然看起来不像 ... 但其实就是把同一个闭包绑定了五次 ...

    我的做法则创建了五个不同的闭包 ... 只有这一点区别 ... 如果你愿意更深入了解的话 ... 去看 this 吧 ...
    pouta
        9
    pouta  
    OP
       Oct 31, 2016
    @wubotao 说到点了
    bayallen
        10
    bayallen  
       Oct 31, 2016
    感觉每个不认真看书的 JavaScript 学习者都会遇到这样的问题……
    learnshare
        11
    learnshare  
       Oct 31, 2016
    经典,可以看看 let 和 var 的差异,以及闭包
    pouta
        12
    pouta  
    OP
       Oct 31, 2016
    @Sunyanzi 谢谢你的耐心解答 最终我是这么写的
    var page = document.getElementsByClassName('swiper-pagination-bullet');
    for(var i = 0;i<page.length;i++){
    page[i].innerHTML = i+1;
    page[i].addEventListener('mouseover',function(){
    var toPage = this.innerHTML;
    mySwiper.slideTo(toPage,1000,true);
    });
    }
    pouta
        13
    pouta  
    OP
       Oct 31, 2016
    @ferrum 我不是前端
    yoa1q7y
        14
    yoa1q7y  
       Oct 31, 2016
    这样解释比较清楚
    addEventListener 中的匿名函数,在这个 for 循环时并不会执行,而 i 始终只有一个,等到 for 循环完成时, i 就变成了 page.length ,等触发点击,执行函数的时候,取到的自然就是 page.length
    pouta
        15
    pouta  
    OP
       Oct 31, 2016
    @yoa1q7y 嗯 很清楚
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3601 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 51ms · UTC 10:34 · PVG 18:34 · LAX 03:34 · JFK 06:34
    ♥ Do have faith in what you're doing.