I have a confusion about IIFE

2020-07-02 10:00发布

问题:

I saw the code below that someone posted. I'm confused about what it logs. It logs variable a the function, not 200. Why?

var a = 1;
(function a() {
  a = 200;
  console.log(a)
})()

回答1:

Because the function being immediately invoked is named, and that name cannot be reassigned to refer to something else directly inside the IIFE.

Any named function expressions will exhibit this behavior as well. A function expression whose function is named a will mean that a directly inside the function will always refer to the function itself, even if you try to reassign it.

You can make the error explicit if you use strict mode:

'use strict';
var a = 1;
(function a() {
  a = 200;
  console.log(a)
})()

Uncaught TypeError: Assignment to constant variable.

Having a named function expression is a bit like having

(function a() {
  const a = <this function>;
  // ...
})()

except trying to reassign it will only throw in strict mode.

Specifically, I believe the ECMAScript 5 specification for this behavior is in SetMutableBinding:

  1. If the binding for N in envRec is a mutable binding, change its bound value to V.
  2. Else this must be an attempt to change the value of an immutable binding so if S (strict mode being used) if true throw a TypeError exception.

But directly inside a function, the function name binding is not mutable - see Function Definition:

The production

FunctionExpression : function Identifier ( FormalParameterListopt ) { FunctionBody }

is evaluated as follows:

Call the CreateImmutableBinding concrete method of envRec, passing the String value of Identifier as the argument.