One, foreword
Javascript functions and scopes
- function
- Function expressions vs function declarations
- Understand arrow functions in depth
- scope
- Lexical scope
- Function scope
- Block scope
var b = 10;
(function b() {
b = 20;
console.log(b)
})()
Copy the code
Second,Function expressions vs function declarations
- The first is syntax
- Function declaration: a function declared as a separate statement in the main code flow.
// Function declaration function sum(a, b) { return a + b; } // The value passed to the function as an argument is copied to the local variable of the function // The function can access external variables. But it only works from the inside out. Local variables inside a function are invisible to code outside the function. // The function can return a value. If no value is returned, undefined is returned Copy the code
- Functional expression: A function created in an expression or another syntactic structure. The following function is created on the right side of the assignment expression =
// Function expression let sum = function(a, b) { return a + b; }; Copy the code
- Nuances: When will the JavaScript engine be created
-
Function declarations, which can be called before a function declaration is defined.
sayHi("John"); // Hello, John function sayHi(name) { alert( `Hello, ${name}` ); } Copy the code
-
Function expressions, created when code execution arrives and available only from that moment.
sayHi("John"); // error! let sayHi = function(name) { // (*) no magic any more alert( `Hello, ${name}` ); }; Copy the code
Simple method distinction
See where the function keyword appears in the declaration. If it is the first word, it is a function declaration; otherwise, it is a function expression.
// This is a function expression, be careful 📢
(function b() {
b = 20;
console.log(b)
})()
Copy the code
conclusion
- Functions are values. They can be assigned, copied, or declared anywhere in the code.
- If a function is declared as a separate statement in the main code flow, it is called a “function declaration.”
- If the function is created as part of an expression, it is called a “function expression.”
- The internal algorithm handles function declarations before executing code blocks. So function declarations are visible anywhere within the block of code in which they are declared.
- Function expressions are created when the execution process arrives.
Recommended priority: function declaration > function expression
Three,Understand arrow functions in depth
Basis:
The arrow function is quite handy for a one-line function. There are two kinds of it:
- Without curly braces:
(... args) => expression
– On the right is an expression: the function evaluates the expression and returns the result. - Curly braces:
(... args) => { body }
— Curly braces allow us to write multiple statements in a function, but we need to explicitlyreturn
To return something.
The introduction of arrow functions is useful in two ways: shorter functions and no binding of this
Depth:
- Arrow function doesn’t have any
this
If you access this, you inherit this from the next level up in your scope chain.
let group = {
title: "Our Group".students: ["John"."Pete"."Alice"].// This. Title is exactly the same as showList. That is: group.title
showList() {
this.students.forEach(
student= > alert(this.title + ':'+ student) ); }}; group.showList();/ / pop up:
// Our Group: John
// Our Group: Pete
// Our Group: Alice
Copy the code
A normal function will return an error:
ForEach is running this function, but this is the default value this=undefined, so we tried to access undefined. Title.
let group = {
title: "Our Group".students: ["John"."Pete"."Alice"].// This is the default value of this=undefined, so we try to access undefined. Title
showList() {
this.students.forEach(function(student) {
// Error: Cannot read property 'title' of undefined
alert(this.title + ':'+ student) }); }}; group.showList();Copy the code
- Arrow function doesn’t have any
arguments
This is useful for decorators when we need to forward a call using the current this and arguments.
For example, defer(f, ms) takes a function and returns a wrapper that calls delay MS milliseconds:
function defer(f, ms) {
return function() {
setTimeout(() = > f.apply(this.arguments), ms)
};
}
function sayHi(who) {
alert('Hello, ' + who);
}
let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // After 2 seconds: Hello, John
Copy the code
Instead of using the arrow function, you could write:
function defer(f, ms) {
return function(. args) {
let ctx = this;
setTimeout(function() {
return f.apply(ctx, args);
}, ms);
};
}
Copy the code
Here, we must create additional variables args and CTX so that the function inside setTimeout can get them.
- Cannot be performed on arrow functions
new
operation
The absence of this naturally implies another limitation: arrow functions cannot be used as constructors. You cannot call them with new.
JavaScript functions have two internal methods: [[Call]] and [[Construct]].
When a function is called from new, the [[Construct]] method is executed to create an instance object, and then the function body is executed to bind this to the instance.
When called directly, the [[Call]] method executes the function body directly.
The arrow function does not have a [[Construct]] method and cannot be used as a constructor. If called from new, an error will be reported.
- Arrow function doesn’t have any
super
If it is accessed, it is retrieved from an external function
Class inheritance
Conclusion:
Arrow functions are for short code that has no “context” of its own, but works in the current context.
Arrow functions don’t have their own (this, arguments, super or new.target), but can use the nearest external function’s (this, arguments, super or new.target).
Lexical scope
Scope: A scope is a set of rules for determining where and how to look for variables (identifiers). If the purpose of the lookup is to assign a value to a variable, an LHS query is used; If the goal is to get the value of a variable, RHS queries are used. The assignment operator causes an LHS query. The = operator or an operation passing in an argument when calling a function results in an assignment of the associative scope.
Scoped lookup: A scoped lookup always starts at the innermost scope of the runtime and works its way up and out until the first matching identifier is found.
Lexical scope: In simple terms, lexical scope is determined by where you write variables and block scopes when writing code, so the lexical analyzer will keep the scope unchanged when processing code.
5. Function scope
The meaning of a function scope is that all variables belonging to the function can be used and reused within the scope of the whole function (or nested scopes)
Adding a wrapper function outside of any fragment “hides” internal variables and function definitions, and the outer scope cannot access anything inside the wrapper function.
var b = 10;
function foo() {
var b = 20;
console.log(b); / / 20
}
foo();
console.log(b); / / 10
Copy the code
Foo is bound to its scope and can be called from foo().
The disadvantage is that:
- You must declare the named function foo(), which pollutes its scope;
- This function must be explicitly called with the function name foo() to run its code.
Using IIFE to solve the above pain points:
- The function name is not required, that is, the function name does not pollute the scope
- It can run automatically
var b = 10;
(function foo() {
var b = 20;
console.log(b); / / 20}) ();console.log(b); / / 10
Copy the code
Foo is bound to a function within the function expression itself, not its scope.
In other words (function foo() {.. })() as a function expression means that foo can only be used in.. Is accessed from the location represented, but not from the external scope.
Vi. Preface Interview question analysis
There are two cases:
var b = 10;
(function b() {
var b = 20 / / the difference
console.log(b); / / 20}) ()Copy the code
Var b = 20; var b = 20; var b = 20; Console. log(b) similarly, the local variable B is found up the scope chain with a value of 20.
var b = 10;
(function b() {
b = 20 / / the difference
console.log(b); }) ()/ / output:
Æ’ b() {
b = 20 / / the difference
console.log(b)
}
Copy the code
When b = 20 is executed, look up the scope chain, find function B, and try to assign b to 20. Because function B is a function expression, and the function name of the function expression is constant, it cannot be assigned twice (silent failure in normal mode, error in strict mode), assignment fails, so the output is still the function
// Output in strict mode
var b = 10;
(function b() {
'use strict'
b = 20;
console.log(b)// "Uncaught TypeError: Assignment to constant variable."}) ()Copy the code
see
-
On JavaScript you Don’t Know
-
Variable scope, closure
-
English version – Variable scope, closures
-
Understand arrow functions in depth
-
MDN arrow function