V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
pouta
V2EX  ›  问与答

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

  •  
  •   pouta · 2016-10-31 15:57:44 +08:00 · 1932 次点击
    这是一个创建于 2938 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 条回复    2016-10-31 17:04:22 +08:00
    ycycwx
        1
    ycycwx  
       2016-10-31 16:01:46 +08:00 via iPhone
    好经典的面试题...
    mlkr
        2
    mlkr  
       2016-10-31 16:05:14 +08:00 via Android
    var 作用域的问题 ,换成 let 试试
    clearbug
        3
    clearbug  
       2016-10-31 16:07:10 +08:00 via Android
    好经典的面试题。。。你需要去看看闭包
    pouta
        4
    pouta  
    OP
       2016-10-31 16:13:55 +08:00
    @ycycwx 不是面试题 是我自己写的时候 遇到的坑
    wubotao
        5
    wubotao  
       2016-10-31 16:20:52 +08:00
    因为执行点击事件时, i 的值已经变成了 page.length
    i 不是取运行时的值,而是取 for 循环完成之后的值
    wubotao
        6
    wubotao  
       2016-10-31 16:21:44 +08:00
    @mlkr 不是作用域的问题,是代码执行顺序的问题。
    Sunyanzi
        7
    Sunyanzi  
       2016-10-31 16:24:24 +08:00
    萌新你好 ... 槽点太多其实不太知道该从何说起 ... 我试试看用最简单的方法跟你解释下吧 ...

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

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

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

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

    我的做法则创建了五个不同的闭包 ... 只有这一点区别 ... 如果你愿意更深入了解的话 ... 去看 this 吧 ...
    pouta
        9
    pouta  
    OP
       2016-10-31 16:37:02 +08:00
    @wubotao 说到点了
    ferrum
        10
    ferrum  
       2016-10-31 16:37:59 +08:00
    感觉每个不认真看书的 JavaScript 学习者都会遇到这样的问题……
    learnshare
        11
    learnshare  
       2016-10-31 16:40:11 +08:00
    经典,可以看看 let 和 var 的差异,以及闭包
    pouta
        12
    pouta  
    OP
       2016-10-31 16:44:48 +08:00
    @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
       2016-10-31 16:46:24 +08:00
    @ferrum 我不是前端
    yoa1q7y
        14
    yoa1q7y  
       2016-10-31 16:49:59 +08:00
    这样解释比较清楚
    addEventListener 中的匿名函数,在这个 for 循环时并不会执行,而 i 始终只有一个,等到 for 循环完成时, i 就变成了 page.length ,等触发点击,执行函数的时候,取到的自然就是 page.length
    pouta
        15
    pouta  
    OP
       2016-10-31 17:04:22 +08:00
    @yoa1q7y 嗯 很清楚
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2786 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:40 · PVG 20:40 · LAX 04:40 · JFK 07:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.