V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
Cielos
V2EX  ›  JavaScript

let 会报错, var 才能正常运行?

  •  
  •   Cielos · 2020-04-09 18:39:38 +08:00 · 3592 次点击
    这是一个创建于 1722 天前的主题,其中的信息可能已经有所发展或是发生改变。
    window.onload = function () {
    var gogogo;
    let btn1 = document.getElementById('btn1');

    btn1.onclick = function () {
    clearInterval(gogogo);
    var gogogo = setInterval(function () {省略...})
    }

    各位好,我刚学 JS 没多久,跟着李立超的视频学的。
    上面这段代码里,如果我把 var gogogo 改成 let,压根就没法运行,请问是什么原因啊?
    还有 clearInterval()应该可以中止定时函数,但是并没有中止,重复点击依然有效,这又是什么情况?

    PS: 李立超的教程是 2016 年录的,当时还没有 LET 吧,像我这样的初学者应该去哪里了解 LET 的详细用法呢?
    26 条回复    2020-04-10 20:54:29 +08:00
    ccyu220
        1
    ccyu220  
       2020-04-09 19:00:22 +08:00
    let 不允许重复声明,都用了 es6 你重复声明 let gogogo 干嘛。
    ccyu220
        2
    ccyu220  
       2020-04-09 19:00:43 +08:00
    baxtergu
        3
    baxtergu  
       2020-04-09 19:07:31 +08:00
    这样改应该就可以了,let 定义的变量名不允许重定义,但是允许重复赋值。

    window.onload = function () {
    let gogogo;
    let btn1 = document.getElementById('btn1');

    btn1.onclick = function () {
    clearInterval(gogogo);
    gogogo = setInterval(function () {省略...})
    }
    useben
        4
    useben  
       2020-04-09 19:08:32 +08:00   ❤️ 5
    我是被头像吸引进来
    wangyzj
        5
    wangyzj  
       2020-04-09 19:28:10 +08:00
    @useben +1
    Cielos
        6
    Cielos  
    OP
       2020-04-09 19:30:59 +08:00
    @baxtergu 仅仅是去掉一个 let 就可以了吗!谢谢大佬!!!
    Cielos
        7
    Cielos  
    OP
       2020-04-09 19:32:51 +08:00
    @ccyu220 谢谢大佬了!所以 var 是可以重复定义的是吗
    ljpCN
        9
    ljpCN  
       2020-04-09 19:45:01 +08:00 via Android
    @Cielos 在你贴的代码里,如果用 var,里面的函数里的和外面的函数里的 gogogo 就不是同一个变量了。
    suckli
        10
    suckli  
       2020-04-09 20:07:41 +08:00
    我是被头像吸引进来
    lzxz1234
        11
    lzxz1234  
       2020-04-10 08:32:21 +08:00
    提问的艺术第一条:换个好头像
    fueen
        12
    fueen  
       2020-04-10 09:16:39 +08:00
    头像+1
    iMiata
        13
    iMiata  
       2020-04-10 09:28:05 +08:00
    头像选得好,绅士少不了
    wgbx
        14
    wgbx  
       2020-04-10 09:57:58 +08:00
    论头像的重要性,var 可以重复声明,let 不允许,ps:var 作为一种过时的声明方式,建议只使用 let 和 const
    ElmerZhang
        15
    ElmerZhang  
       2020-04-10 10:19:57 +08:00
    建议楼主读一下 《 ES6 标准入门》
    ElmerZhang
        16
    ElmerZhang  
       2020-04-10 10:21:16 +08:00
    除非完全没有编程基础,否则学习一门新语言时最好买本书从基本语法入手。
    werty
        17
    werty  
       2020-04-10 11:13:24 +08:00
    头像+1
    Curtion
        18
    Curtion  
       2020-04-10 14:49:33 +08:00
    这是因为 let 暂时性死区问题,onclick 中调用 clearInterval 函数时会用到 gogogo 变量,此时因为使用了 let 所有存在 TDZ 问题,导致并不会向上级作用域寻找 gogogo 变量,所有会报 Cannot access '' before initialization 错误。

    clearInterva 没有中止有两个原因,一是因为 onclick 中使用了 var 定义变量,每次点击时的 gogogo 都是新的,结果就是不但没有停止,每次点击时还新建了一个定时器;如果把 var 去后也无法停止,原因是虽然停止了定时器,但是又新建了一个定时器。


    我感觉很奇怪的就是:
    console.log(a)
    let a = "1"
    报的错误是:Uncaught ReferenceError: a is not defined


    而:
    function main() {
    console.log(a)
    let a = "1"
    }
    main()
    报的错误是:Uncaught ReferenceError: Cannot access 'a' before initialization

    我怎么感觉这是同一种错误....
    djs
        19
    djs  
       2020-04-10 15:27:16 +08:00 via iPhone
    let 可以导致暂时性死区,在你用的 let 那个位置,要先生命变量才行
    vivipure
        20
    vivipure  
       2020-04-10 15:37:59 +08:00
    建议 直接看 ruanyifeng 的 ES6 或者 MDN 文档
    kingthy
        21
    kingthy  
       2020-04-10 16:42:46 +08:00
    @Curtion 是同一个错误,ReferenceError,只是描述不一样,你把它看为第一种是编译期错误,第二种是运行期错误。比如第二种 function main() {
    console.log(a)
    let a = "1"
    }
    kingthy
        22
    kingthy  
       2020-04-10 16:43:17 +08:00
    怎么自动发布了,补上面:
    kingthy
        23
    kingthy  
       2020-04-10 16:44:07 +08:00
    怎么自动发布了,补上面:方法定义后不执行是可以“编译”通过的
    ourFEer
        24
    ourFEer  
       2020-04-10 17:39:59 +08:00
    我是被头像吸引进来的
    Cielos
        25
    Cielos  
    OP
       2020-04-10 19:38:29 +08:00
    非常感谢大家的回答!
    theohateonion
        26
    theohateonion  
       2020-04-10 20:54:29 +08:00
    @ccyu220 并不是 let 不允许重复声明,而是 18 楼说的死区问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5856 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 02:24 · PVG 10:24 · LAX 18:24 · JFK 21:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.