node.js (Windows) 对 IIFE 的奇怪观察
strange observation on IIFE in node.js (Windows)
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");
}());
它产生
welcome
hello
我不得不相信节点解析错误地假定 嵌套 IIFE (function(){...})()) 首先执行并且 IIFE 触发器的外部 ()在它上面执行函数定义(如果我在 abc 定义和 IIFE 之间引入注释行也没关系)。
导致您出现问题的原因是缺少分号。
var abc = function(){
console.log("hello");
}; // missing semicolon!
(function(){
console.log("welcome");
})();
这不仅仅是一个 node.js 问题。您将在浏览器中遇到相同的错误。正如其他人所提到的,错误是第一个函数中缺少分号。但是这是怎么回事?
好吧,首先让我们解释一下到底什么是IIFE。您可能知道以下语法:
(function(){})();
但这不是 IIFE 的唯一语法。 IIFE 即立即调用函数表达式。所以它是在声明后立即调用一个函数表达式。
那么,什么是函数表达式?它只是一个在表达式上下文中声明的函数。在表达式上下文中求值的一种方法是使用大括号运算符:()
。在这里,大括号运算符实际上与数学中的大括号运算符相同:它强制执行数学运算的优先级。
所以这里的大括号:
(function(){})
意思和这个完全一样:
(1+1)
它告诉解释器,它里面的代码是一个表达式,return是一个值。这就是表达式上下文的意思 - 任何地方都可以对 return 值进行计算。
语言在其他地方解释为表达式上下文。其中之一紧跟在操作员之后。例如 !
运算符或 -
运算符(使数字为负数)。所以,例如你可以这样写:
-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,通过将第二个函数作为参数传递来调用它,并尝试调用第一个函数的 return 值(这是未定义的,因为您没有return 除了记录“你好”之外什么都没有。
换句话说,如果我们分解它,它就是这样做的:
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 的方法不止一种。
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");
}());
它产生
welcome hello
我不得不相信节点解析错误地假定 嵌套 IIFE (function(){...})()) 首先执行并且 IIFE 触发器的外部 ()在它上面执行函数定义(如果我在 abc 定义和 IIFE 之间引入注释行也没关系)。
导致您出现问题的原因是缺少分号。
var abc = function(){
console.log("hello");
}; // missing semicolon!
(function(){
console.log("welcome");
})();
这不仅仅是一个 node.js 问题。您将在浏览器中遇到相同的错误。正如其他人所提到的,错误是第一个函数中缺少分号。但是这是怎么回事?
好吧,首先让我们解释一下到底什么是IIFE。您可能知道以下语法:
(function(){})();
但这不是 IIFE 的唯一语法。 IIFE 即立即调用函数表达式。所以它是在声明后立即调用一个函数表达式。
那么,什么是函数表达式?它只是一个在表达式上下文中声明的函数。在表达式上下文中求值的一种方法是使用大括号运算符:()
。在这里,大括号运算符实际上与数学中的大括号运算符相同:它强制执行数学运算的优先级。
所以这里的大括号:
(function(){})
意思和这个完全一样:
(1+1)
它告诉解释器,它里面的代码是一个表达式,return是一个值。这就是表达式上下文的意思 - 任何地方都可以对 return 值进行计算。
语言在其他地方解释为表达式上下文。其中之一紧跟在操作员之后。例如 !
运算符或 -
运算符(使数字为负数)。所以,例如你可以这样写:
-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,通过将第二个函数作为参数传递来调用它,并尝试调用第一个函数的 return 值(这是未定义的,因为您没有return 除了记录“你好”之外什么都没有。
换句话说,如果我们分解它,它就是这样做的:
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 的方法不止一种。