Javascript JSlint:在函数范围内重新定义i

Javascript JSlint:在函数范围内重新定义i,javascript,jslint,Javascript,Jslint,通过JSLint运行以下Javascript代码时: (function () { var i = 'a'; console.log(i); function foo () { var i = 'b'; console.log(i); } foo(); console.log(i); foo(); }());

通过JSLint运行以下Javascript代码时:

    (function () {
        var i = 'a';

        console.log(i);

        function foo () {
            var i = 'b';
            console.log(i);
        }

        foo();

        console.log(i);

        foo();
    }());
我在JSLint中得到以下错误:

    #1 Redefinition of 'i' from line 4.
       var i = 'b'; // Line 7, Pos 13
    #2 Unused 'i'.
       var i = 'a'; // Line 4, Pos 9
    #3 Unused 'foo'.
        function foo () { // Line 6, Pos 14
我的问题是:

  • 当我明确地调用foo()时,为什么它会说foo()未使用

  • 为什么它说作用域为
    var i='b'
    的函数是它上面的函数的重新定义

  • 为什么它说第一个
    var i='a'
    定义未使用


  • 您将得到
    i
    的重新定义,因为它存在于两个作用域中


    这本身并不是一个真正的问题,但是Crockford认为这是一件会引起混淆的事情,所以他的工具会捕捉到它。

    首先,如果在jslint.com上运行代码,您只会得到重新定义错误,这是有效的。所以我不确定你为什么会看到错误1和3。你还好吗?它是否在另一个应用程序中?您使用的jslint.js的日期是什么?等等

    /*jslint sloppy:true, white:true, browser:true, devel:true */
    (function () {
        var i = 'a';
    
        console.log(i);
    
        function foo () {
            var i = 'b';
            console.log(i);
        }
    
        foo();
    
        console.log(i);
    
        foo();
    }());
    
    那只给了我

    Redefinition of 'i' from line 3.
                var i = 'b';
    
    很公平。在你的问题的评论中,帕斯蒂也做了同样的交易。正如杰里米所说,密码不会被破解。只是让人困惑。为什么不在
    foo
    中使用
    j
    (当然,也可以在live code中使用描述性变量名),或者在pastie的
    中使用匿名函数

    当您使用JSLint时,请务必记住,“当使用难以区分明显错误的习惯用法时,编写正确的程序是很困难的。”用
    foo
    的内部
    i
    覆盖您的外部
    i
    是令人困惑的

    想象一下如果
    foo
    read

        function foo () {
            console.log("Maybe I think I'm getting old 'i' here: " + i);
    
            var i = 'b';
            console.log(i);
        }
    
    JSLint(奇怪的是,如果你问我的话)并不要求
    var
    语句是每个作用域的第一行,只要求它发生在引用变量之前

    因此,如果您使用新的
    foo
    运行测试代码,那么在到达变量的声明语句b/c之前,
    foo
    i
    将被取消定义。奇怪吧?(或预期,取决于您的JS体验!)

    你可能会说JSLint错了——它不仅应该抱怨
    的重新定义,还应该抱怨
    'i'在定义之前就被使用了。
    foo
    的范围内。我不会争辩的


    然而,我要说的是,重新定义是一个很难与明显错误区分开来的习语。最佳实践?不要对重叠作用域中的不同值重复使用变量名。

    先声明函数,然后再声明
    var
    ,这样声明的顺序就正确了,JSLint就不会报告任何错误。@Teemu:也许更好的例子是将闭包用作回调。如果在该闭包中定义
    var i
    ,JSLint会报告相同的错误,这都与提升有关。函数和变量声明被提升到其作用域的顶部,函数应该是第一个,然后是变量。如果它们的顺序不正确,JSLint会报告一个错误,显然无法正确处理其余的代码,至少从人的角度来看,“未使用的变量”感觉不合逻辑。好吧,也许是一个更好的问题——为什么我在这里得到“我”的重新定义:很难说,也许你必须问Crockford先生;)。谢谢,很好地解释了它背后的原因。
    a
    Maybe I think I'm getting old 'i' here: undefined
    b
    a
    Maybe I think I'm getting old 'i' here: undefined
    b