strange observation on IIFE in node.js (Windows)

喜欢而已 提交于 2019-12-31 04:52:10

问题


Is the below behavior expected for nodejs? It looks buggy to me. If not what am I missing?

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

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

I get the below exception

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

If I alter the code to

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

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

it produces

welcome hello

I'm forced to believe node parsing mistakenly assumes nested IIFE (function(){...})()) executed first and and outer () of IIFE triggers execution of function definition above it (it does not matter if I introduce a comment line in between abc definition and IIFE).


回答1:


It's not just a node.js problem. You'll get the same error in the browser. As mentioned by others the bug is the missing semicolon in the first function. But what's going on?

Well, first let's explain what exactly is an IIFE. You may be aware of this syntax:

(function(){})();

But it's not the only syntax for IIFE. IIFE is Immediately Invoked Function Expression. So it is invoking a function expression immediately after declaring it.

So, what is a function expression? It is simply a function declared in expression context. One way to evaluate something in expression context is to use the brace operator: (). Here, the brace operator is actually the same brace operator in math: it enforces precedence of math operations.

So the braces in this:

(function(){})

mean exactly the same as this:

(1+1)

It tells the interpreter that the code inside it is an expression that returns a value. So that's what expression context means - any place you can do calculations to return values.

There are other places where the language interprets as expression context. One of them is immediately after an operator. For example the ! operator or the - operator (to make a number negative). So, for example just as you can write:

-12 + 5

you can also write an IIFE like this:

-function(){}()

Another place that javascript interprets as expression context is everything to the right of an = sign. For example:

var x = 12 + 5;

Which means, you can write an IIFE like this:

var x = function(){}();

This is what's causing problems in your code. Basically, javascript interprets your code like this:

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

That is, your first function is treated as an IIFE and it is called by passing your second function as an argument and tries to call the return value of the first function (which is undefined because you don't return anything but just log "hello").

In other words, if we break it down, it's doing this:

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

The lesson is, you don't need a semicolon after a function declaration but you need it after a function expression.

Second, less useful lesson: there's more than one way to IIFE.




回答2:


A missing semicolon is the cause of your issues.

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

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


来源:https://stackoverflow.com/questions/30010640/strange-observation-on-iife-in-node-js-windows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!