在哪里可以定义功能

时间:2018-12-17 11:41:34

标签: javascript scope

已编辑:表达式function foo() {return 20;}, foo()console.log的单个参数。

此:

console.log((function foo() {return 20;}, foo()));

不起作用,我得到ReferenceError,因为尚未定义foo

为什么?

3 个答案:

答案 0 :(得分:9)

console.log(function foo() {return 20;}, foo());

在这段代码中,您要传递一个名为 foo)的函数作为console.log的参数。得到它了?您从未声明函数foo,只是将其作为参数传递。在javascript中,函数声明和函数表达式具有相同的语法,因此造成混淆。

也就是说,传递一个名为 (而不是 anonymous )的函数几乎总是无用的。您的代码与此等效:

console.log(function () {return 20;}, foo());

其中function () {return 20;}是匿名函数,与命名函数相反。而且,匿名函数在JS中的使用非常广泛,因为同样,命名函数表达式中的名称几乎没有用。

答案 1 :(得分:3)

更新

我看到您编辑了原始问题。由于您实际上只向console.log()传递了一个参数,因此我相信在这种情况下,您收到ReferenceError的原因是因为当您使用这样的逗号时,该函数语法被视为函数表达式而不是函数声明。因此,它是一个命名函数,但不是声明的函数,并且对于foo()表达式仍然不在范围内。

有关声明和语句与表达式的更多信息,请参见http://2ality.com/2012/09/expressions-vs-statements.html,尤其是“函数表达式与函数声明”部分。

要清楚,这(单独一行)将是一个函数声明:

function foo() {return 20;})

这是在定义变量并将其分配给命名函数 expression

const foo = function foo() {return 20;})

在您的代码中,实际上您正在创建一个函数 expression ,即使它看起来像是一个函数 declaration


可以在允许使用语句或表达式的任何位置定义函数。因此,您的代码的语法是有效的,但是它无效,因为表达式的作用域仅限于定义它们的位置。在这种情况下,第二个参数无法访问第一个参数中的foo函数。类似于使用letconst时,变量无法在其块之外访问,例如:

if (someCondition) {
    const foo = () => 20
    console.log(foo())  // works
}
console.log(foo())  // doesn't work: Uncaught ReferenceError: someCondition is not defined

因此,如果您需要在console.log()的参数中调用函数,则需要在console.log()语句之外声明外部,例如:

function foo() {return 20;}
console.log(foo());

或者,就像其他人提到的那样,您可以使用IIFE(立即调用的函数表达式),因为它不会尝试从console.log()的第二个参数位置访问该函数(它只涉及一个参数):

console.log((function foo() {return 20;})())

...但是实际上,这是对IIFE的不良使用;没有必要在这里这样做。

答案 2 :(得分:2)

使用console.log的每个“日志”将输出在调用console.log的范围内注册的值。

在您的情况下,您正在console.log的调用内定义一个函数,此命名函数将仅在其中定义。 您需要在console.log 之外定义函数,以便输出其值。

第二个参数的行为类似于第一个参数,并将在全局范围内搜索值。它无法查找第一个参数中定义的值。