17

我有以下代码:

if (typeof console === "object" && typeof console.error === "function") {
    function e(msg) {"use strict"; console.info(msg);}
}

对于哪个 jsLint 给出以下错误:

函数语句不应放在块中。使用函数表达式或将语句移动到外部函数的顶部。

为什么会出现此错误,这是什么意思?

4

2 回答 2

50

解释

从关于警告功能语句的 jsLintErrors 页面不应将其放在块中

引发此错误是为了突出显示可能无法按预期工作的代码。在大多数环境中,您的代码将毫无错误地运行,但可能不会以您期望的方式运行。在某些环境中,它可能会导致致命的语法错误

这是因为Function声明被提升到它们出现的范围的顶部。

因此,不可能使用块语句有条件地声明函数。

例子

让我们通过一个简单的例子来探讨这个问题引发的问题:

if (true) {
    function example() {
        console.log('hello');
    }
}

最好的情况是您的代码令人困惑。在上面的例子中,看起来你想做的只是在条件为真时声明对函数访问。然而,当函数被提升到作用域的顶部时,它实际上会被解释为:

function example() {
    console.log('hello');
}
if (true) {}

这是危险的,因为它看起来不像您根据原始代码所期望的那样。条件块实际上是空的(并且是不必要的),并且每个人都可以访问该函数,无论条件评估为真还是假。

最坏的情况是浏览器不明白如何处理嵌套函数,并在尝试使用它时抛出语法错误。这取决于运行 JavaScript 的引擎。Firefox 似乎就是这样一种引擎。如果在 Firefox 中运行以下代码,在执行以下代码时会抛出错误:

if (true) {
    example();
    function example() {
        console.log('hello');
    }
}

如果您打开控制台,您应该会看到以下错误:

ReferenceError:未定义示例

解决方案

那么你怎么能解决这个问题呢?

使用函数赋值而不是函数声明

这是一个快速细分:

// Declaration
function declarationFunction() {}

// Assignment
var assignmentFunction = function() {}

函数分配不会提升到范围的顶部
函数声明被提升到范围的顶部。

因此,要有条件地设置示例函数,只需在块中分配它,如下所示:

var example;
if (true) {
    example = function() {
        console.log('hello');
    }
}
于 2014-11-05T22:18:30.140 回答
11

您不应该在 if 块内创建函数。你最好这样做:

var e = function(){};

if(typeof console === "object" && typeof console.error === "function"){
    e = function (msg){ ... };
}
于 2013-01-20T17:25:02.540 回答