【问题标题】:strange observation on IIFE in node.js (Windows)在 node.js (Windows) 中对 IIFE 的奇怪观察
【发布时间】:2015-07-12 16:31:12
【问题描述】:

nodejs 会出现以下行为吗?对我来说它看起来很糟糕。如果不是,我错过了什么?

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

(function(){
  console.log("welcome");
})();

我得到以下异常

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

如果我将代码更改为

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

(function(){
  console.log("welcome");
}());

它产生

欢迎 你好

我不得不相信节点解析错误地假设 nested IIFE (function(){...})()) 首先执行并且 IIFE 的外部 () 触发执行上面的函数定义它(如果我在 abc 定义和 IIFE 之间引入注释行也没关系)。

【问题讨论】:

  • 缺少分号会导致问题。

标签: javascript node.js iife


【解决方案1】:

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

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

(function(){})();

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

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

所以这里的大括号:

(function(){})

意思和这个完全一样:

(1+1)

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

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

-12 + 5

你也可以这样写一个 IIFE:

-function(){}()

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

var x = 12 + 5;

也就是说,你可以这样写一个 IIFE:

var x = function(){}();

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

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

    缺少分号是导致问题的原因。

    var abc = function(){
    console.log("hello");
    }; // missing semicolon!
    
    (function(){
      console.log("welcome");
    })();
    

    【讨论】:

    • 是的,这是真的。我刚刚被空白解析所吸引。 JS 解析器似乎可以使用 (function(){...} /*nonwhitespace but comment*/ ());
    • @Baski:C 和 Java 的行为方式相同 - 您可以在函数名和 () 之间插入大量空格
    猜你喜欢
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    相关资源
    最近更新 更多