为什么JSLint会抱怨未定义/暗示的全局变量?

4
我正在尝试理解为什么JSLint会在以下示例中抱怨隐含的全局变量:
var TEST = (function () {
  var count = 0;

  function get_count() { 
    return add_one(); 
  }

  function add_one() {
    count += 1;
    return count;
  }

  return { 
    get_count: get_count
  };
}());

在JSLint中运行此代码会出现错误:

第5行第12个字符存在问题:'add_one'未定义。

同时还会提示:

隐式全局变量:add_one 5

如果您将add_one()函数移动到get_count()函数之前,则不会出现错误。但是,使用上面的代码时,在浏览器中运行它时不会产生任何错误。有人能解释一下为什么JSLint会抱怨吗?

谢谢!
马特

3个回答

11
这是因为 JSLint 使用自顶向下的解析器——Pratt Parser,而不是一个完整的 JavaScript 解释器。如果它真的被解释了,那么它就不会给你那个错误。 add_one 是一个隐式全局变量,因为解析器还没有遇到该变量,所以它假定你的周围代码将拥有该变量。但是,如果你把它颠倒过来,那么解析器已经遇到了 add_one 变量,一切都很好 :-)
顺便说一下,我注意到你闭合函数的最后一行有一个小错误:}() 应该是 })()

2
+1 正确。只要它们没有作用域限制,即 var a = function() { },JavaScript 会在您调用代码下方使函数可用。 :) - alex
1
啊哈,好的。谢谢Jacob,这很有道理。现在我明白了,我可以克服JSLint伤害我的感情了。还要感谢您纠正我的代码! - m4olivei
+1 对于 JSLint 伤害你的感情。你不是一个糟糕的程序员! - Daniel T.
1
如果我的理解是正确的,那么 }()); 被推荐使用而不是 })(); 参考 https://dev59.com/2HM_5IYBdhLWcg3wRw11#1450768 - Factor Mystic

1
如果我改变方法声明的顺序,它将解决你的问题。如另一个答案中所提到的,一些JavaScript解析器使用自上而下的方法来读取代码,类似于C编程语言的方式。现代解释器和编译器使用两个阶段的方法。第一阶段是将方法读取/编译到内存中。如果遇到任何它不知道的方法调用,它将查找整个内存中的方法集以确定它是否存在。我建议修复顺序,因为虽然它可能不会引起问题,但它会更早地将方法加载到内存中。
var TEST = (function () {
  var count = 0;

  function add_one() {
    count += 1;
    return count;
  }

  function get_count() { 
    return add_one(); 
  }

  return { 
    get_count: get_count
  };
}());

1

你会得到“add_one未定义”的错误,因为JSLint认为函数表达式应该按正确顺序声明。对于另一个问题(“暗示全局变量:add_one 5”),只需在脚本顶部添加注释,例如/*globals add_one*/即可解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接