This is a summary of the scope section in the ECMAScript 6 Getting Started function Parameter Defaults chapter, and looks at some related issues, as well as a translation issue with Babel.
Parameter default value and scope
Reference for this section:
- Understanding the default values of es6 function parameters? Answer by dablwow80
- ECMAScript introduction to 6
- The third scope caused by the parameter default value
- ECMAScript ® 2015 Language Specification
- Js variable declaration function declaration variable assignment implementation mechanism doubt? – Answer to the aurora – Zhihu
- Order of function execution
In the ECMA – 262 9.2.12 FunctionDeclarationInstantiation (func, argumentsList) chapter related instructions.
When parsing the execution context of a JS function, a new Environment Record (ER) is created and each instantiated parameter in the ER is bound. Each declaration in the function body is also instantiated.
-
If the parameters do not have any default values, the function body declaration is instantiated in the same ER as the parameters. That is, declarations in the body of a function are instantiated in the same ER as parameters.
-
Function parameters are added to the scope of the function, and the parameters are not redefined (using var to declare variables with the same name as the parameter is ignored).
function fun(arg1, arg2) { var arg1; // The declaration is ignored var arg2 = "hello"; // var arg2 declaration is ignored and arg2 = "hello" is executed console.log(arg1, arg2); } fun(1.2); // 1 "hello" Copy the code
-
ES6 lets and const will report errors due to repeated declarations in scope
function fun(arg) { let arg; } fun(); // SyntaxError: Identifier 'arg' has already been declared Copy the code
-
One more case is if a function is declared with the same name as the parameter
Prior to ES6, the execution of a function could be divided into three stages (after ES6 things became more complicated and unknown) :
- To prepare. This includes parameter creation, function body preresolving (var declaration and function declaration promotion, that is, reactive), and function declaration creation
- Load, that is, populate data. Loading order is
Function parameters
>Function declaration
If there is a function declaration in the function body with the same name as the parameter, the function overrides the parameter - Execution, slightly
function fun(arg) { console.log(arg); function arg() { / /... } } fun(1); // [Function: arg] Copy the code
- In preparation, create parameters
arg
, function body preparse, create function declaration - During the load phase, the parameter 1 is assigned to
arg
.arg = 1
There is a function declaration in the function bodyfunction arg(){}
, so the function specification is assigned toarg
, that is,arg = function(){}
-
PS: The above cases are only summarized through performance and results, and are not analyzed strictly in accordance with the specifications. If you are wrong, please feel free to comment.
-
When a function is executed, if there is a default value for the function parameter, a second ER is created. This scope is for the declaration in the function body, so the declaration in the function body is not in the same scope as the function declaration of the parameter and itself
So a function declaration with default parameters defined in a global environment generates at least three scopes at runtime, as shown below:
-
Variables in ER of a parameter can only read variables in ER or outside of the function. Variables in a function can read variables in a function, a parameter, and outside of the function
-
Inside a function, you can change the values of parameters defined in ER, but you cannot redefine parameters
- with
var
Just because a variable is declared as a Block does not mean it is block-level scoped, whileJust to distinguish parametersER
And the body of the functionER
- with
-
A question
var x = 20;
function fun(x = 1) {
debugger;
var x = 10;
console.log(x);
}
fun(2);
Copy the code
Since the parameter scope and the function body scope do not share, why should a variable declared using var in the function body scope have an initial value that is the same as the value instantiated by the parameter?
I hope someone senior can answer my questions.
Analyze a few small examples:
-
Parameters are individually scoped
let x = 1; function fun(x, y = x) { console.log(y); } fun(2); Copy the code
- parameter
y
The default value of thex
- Call a function
fun
, the parameter forms a separate scope - In this scope, the default value variable points to the first parameter
x
, not the global environmentx
- parameter
-
Scopes created by parameters with default values also look for variables along the scope chain
function fun(y = x) { let x = 2; console.log(y); } fun(); // ReferenceError: x is not defined Copy the code
- Call a function
fun
When the parametery=x
Form a separate scope - In this scope, there is no definition
x
, so look for variables globally along the scope chainx
- There are no variables defined in the global environment
x
, so an error will be reported - When a function is called, the local variable x inside the function body does not affect the parameter default variable x
- Call a function
-
Avoid temporary Dead Zones (TDZ)
let x = 1; function fun(x = x) {} fun(); // Uncaught ReferenceError: x is not defined Copy the code
- parameter
x = x
Form a separate scope - In this scope, the execution is
let x = x
That’s how temporary death zones form
- parameter
If the default value of the argument is a function, the scope of that function also follows the rules above
let foo = "outer";
function bar(func = () => foo) {
let foo = "inner";
console.log(func());
}
bar(); // outer
Copy the code
- function
bar
The parameters of thefunc
The default value of is an anonymous function that returns a variablefoo
- Parameters are formed in a separate scope, and no variables are defined
foo
, so pointing to the outer global variablefoo
A Babel problem
Reference for this section:
- Extensions to ES6 functions
- Understanding the default values of es6 function parameters? Answer by dablwow80
- Babel translation
In ruan yifong’s introduction to ECMAScript 6, there was an example of a complex parameter default that was translated by Babel to behave differently than before.
-
ES6
var x = 1; function foo( x, y = function() { x = 2; } ) { var x = 3; y(); console.log(x); } foo(); / / 3 Copy the code
- Since parameters have default values, the parameters of a function form a separate scope
y
The default value of is an anonymous function, a variable within the functionx
The first parameter pointing to the same scopex
- An internal variable is also declared inside the function body
x
, the variable and the first parameterx
It is not the same variable because it is not the same scope - perform
y
After, internal variables and external variablesx
The value of alpha is the same
-
After translation into ES5 ([email protected]), the result was found to be different from the original result. The reason is that the scope of the parameter and the function body is not separated after translation
"use strict"; var x = 1; function foo(x) { var y = arguments.length > 1 && arguments[1]! = =undefined ? arguments[1] : function() { x = 2; }; var x = 3; y(); console.log(x); } foo(); / / 2 Copy the code
-
Modified based on Babel
function foo(x) { var y = arguments.length > 1 && arguments[1]! = =undefined ? arguments[1] : function() { x = 2; }; return function() { var x = 3; y(); console.log(x); }.call(this, x, y); } Copy the code
Babel may not have changed it for some reason, but the result is that the translated code does not match the original result.
conclusion
In fact, I still find it difficult to analyze this problem. I cannot analyze the reason from ECMAScript® 2015 Language Specification, that is, I cannot fundamentally explain the complete operation principle. It’s more about learning from other people’s understanding.
In fact, this problem rarely appears in business scenarios and has more research significance than practical significance.
reference
- Understanding the default values of es6 function parameters? Answer by dablwow80
- ECMAScript introduction to 6
- The third scope caused by the parameter default value
- ECMAScript ® 2015 Language Specification
- Js variable declaration function declaration variable assignment implementation mechanism doubt? – Answer to the aurora – Zhihu
- Order of function execution