在 node.js (Windows) 中对 IIFE 的奇怪观察

Bas*_*ski 2 javascript node.js iife

nodejs 是否需要以下行为?对我来说它看起来很糟糕。如果不是我错过了什么?

var abc = function(){
console.log("hello");
}

(function(){
  console.log("welcome");
})();
Run Code Online (Sandbox Code Playgroud)

我得到以下异常

TypeError: undefined is not a function
    at Object.<anonymous> (C:\node\main.js:8:3)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3
Run Code Online (Sandbox Code Playgroud)

如果我将代码更改为

var abc = function(){
console.log("hello");
}

(function(){
  console.log("welcome");
}());
Run Code Online (Sandbox Code Playgroud)

它产生

欢迎你好

我不得不相信节点解析错误地假设嵌套的 IIFE (function(){...})())首先执行,而 IIFE 的外部 () 触发它上面的函数定义的执行(如果我引入一个abc 定义和 IIFE 之间的注释行)。

sle*_*man 7

这不仅仅是 node.js 的问题。你会在浏览器中得到同样的错误。正如其他人所提到的,错误是第一个函数中缺少分号。但是发生了什么?

好吧,首先让我们解释一下什么是IIFE。您可能知道以下语法:

(function(){})();
Run Code Online (Sandbox Code Playgroud)

但这不是 IIFE 的唯一语法。IIFE 是立即调用函数表达式。所以它在声明后立即调用一个函数表达式。

那么,什么是函数表达式?它只是一个在表达式上下文中声明的函数。在表达式上下文中求值的一种方法是使用大括号运算符:()。在这里,大括号运算符实际上与数学中的大括号运算符相同:它强制执行数学运算的优先级。

所以这里的大括号:

(function(){})
Run Code Online (Sandbox Code Playgroud)

意思与此完全相同:

(1+1)
Run Code Online (Sandbox Code Playgroud)

它告诉解释器里面的代码是一个返回值的表达式。所以这就是表达式上下文的意思 - 任何可以进行计算以返回值的地方。

语言在其他地方将其解释为表达式上下文。其中之一是紧跟在操作员之后。例如!运算符或-运算符(使数字为负)。因此,例如,就像您可以编写的那样:

-12 + 5
Run Code Online (Sandbox Code Playgroud)

你也可以像这样写一个 IIFE:

-function(){}()
Run Code Online (Sandbox Code Playgroud)

javascript 解释为表达式上下文的另一个地方是=符号右侧的所有内容。例如:

var x = 12 + 5;
Run Code Online (Sandbox Code Playgroud)

这意味着,您可以像这样编写 IIFE:

var x = function(){}();
Run Code Online (Sandbox Code Playgroud)

这就是导致您的代码出现问题的原因。基本上,javascript 会像这样解释您的代码:

var abc = function(){
    console.log("hello");
}(function(){console.log("welcome")})();
Run Code Online (Sandbox Code Playgroud)

也就是说,您的第一个函数被视为 IIFE,通过将您的第二个函数作为参数传递并尝试调用第一个函数的返回值来调用它(这是未定义的,因为您不返回任何内容,只是记录“hello ”)。

换句话说,如果我们分解它,它会这样做:

function first_function () { console.log('hello') }

function second_function () { console.log('world') }

var temp = first_function(second_function);
var abc = temp(); // it errors here because temp is undefined
Run Code Online (Sandbox Code Playgroud)

教训是,在函数声明之后不需要分号,但在函数表达式之后需要分号。

第二,不太有用的教训:IIFE 的方法不止一种。