Functions are objects

First, the definition of the function

1. Use constructors (formal, but no one uses them)

Let variable name = new Function(' form parameter 1',' form parameter 2', statement,' return value ')

  • For example:let f = new Function('x,y','return x+y')
  • All functions areFunctionconstructed
  • Including Object, Arry, Function

Named functions

Function Name (formal argument 1, formal argument 2) {return value}

  • For example:function add(x,y) {return x+y}
  • let f1 = function add(x,y) {return x+y}We could also put a named function on the f1 variable, but in this case we could not call the named function with the name add. The scope of add is limited to the right side of the equal sign.

Anonymous functions

Let variable name = function (form parameter 1, form parameter 2)

  • Because the anonymous function has no name, the function expression must be assigned to the variable. The variable stores the address of the anonymous function
  • If you drop the name of a named function it’s an anonymous function, also known as a function expression.
  • Let f1 = function(x,y){return x+y}

Arrow function

Let variable name = (formal parameter) => {statement return value}

  • Since the arrow function has no name, we must assign this arrow function to the variable f1. The variable stores the address of the arrow function
  • When there is only one formal argument, you can omit the parentheses ()
  • {} can be omitted if only the return value is available. But if the return value is an object, {} can be buggy! Just add a () to the object
let f1 = x= > x*x

let f2 = (x,y) = > x+y // The parentheses cannot be saved

let f3 = (x,y) = > {return x+y} // Curly braces cannot be omitted

let f4 = (x,y) = > {
    console.log('hi')
    return x+y
}

let f5 = x= > ({name:x})
Copy the code

The function itselffnVS function callfn()

1. Function fn itself

Fn is the function itself

Function fn()

· Fn () can only call this function if it gives the function the arguments it needs (i.e., parentheses for ())

let fn = () = > {console.log('hi')}
fn
// There is no result because fn is not executed
let fn = () = > console.log('hi')
fn()
// Print hi with parentheses
fn2  // () => {console.log('hi')}
fn2()  // hi

/* fn saves the address of the anonymous function which is copied to fn2. Fn2 () calls the anonymous function fn and fn2 are references to anonymous functions. The real function is neither fn nor fn2 but () => {console.log('hi')} */
Copy the code

Three, the elements of the function

  • Call timing: The definition is defined, but when does the call return a value based on the specific situation
  • Scope: The proximity principle
  • closure
  • Formal parameters
  • The return value
  • The call stack
  • Function increase
  • Arguments (except for arrow functions)
  • This (except for the arrow function)

1. Call timing

let a = 1

function fn(){
setTimeout(() = >{
console.log(a)
},0)
}

fn()
a = 2
/ / 2
// Print a later, meaning wait for all code to finish executing
Copy the code
let i = 0

for(i = 0; i<6; i++){
setTimeout(() = >{
console.log(i)
},0)}// Print out six sixes
// Loop through each I to print out I after a while. After a while, it means to finish all the loops. So when the loop is done, I is 6, so I have to print out six 6's
Copy the code
for(let i = 0; i<6; i++){
setTimeout(() = >{
console.log(i)
},0)}// Prints 0, 1, 2, 3, 4, 5
// Updates have been made to cater to the new crowd
// If we use for and let together in JS, we will create one more I per loop
Copy the code

2. Scope

1. Top-level scope

2. Local scope

  • Each function creates a local scope by default
  • Variables declared in a local scope are local variables

3. Global variables

  • Variables declared in the top-level scope are global variables
  • The properties of the window are global variables
  • Global variables exist in any scope

4. All other variables are local

  • Local variables exist only in the local scope

5. Functions can be nested, and scopes can be nested

6. If multiple scopes have the same name as variable A, then when looking for the declaration of a, we will look up the nearest scope (of course, we are not looking up the nearest package scope), for short"Proximity Principle". The process of finding the declaration of A (also equivalent to the scope of the scope) is independent of function execution, but the value of a is 7. A scope independent of the execution of a function is called a static scope (lexical scope)

A scope associated with the execution of a function is called a dynamic scope

3. The closure

If a function uses an external variable, then that function plus that variable is called a closure

4. Formal parameters

  • Formal parameters just mean non-actual parameters.
  • Parameters can be thought of as variable declarations.
  • There can be as many or as few parameters
function add(x, y){return x+y}
// where X and y are parameters, since they are not actual arguments
add(1.2)
// When add is called, 1 and 2 are the actual arguments assigned to xy
Copy the code

5. The return value

1. Every function returns a value. If no return is written, the return value is undefined

2. A value is returned only after the function is executed

3. Only functions return values.

4. All other expressions are called values. For example, 1+2 equals 3

function hi(){ console.log('hi') }
hi()  //undefined
function hi(){ return console.log('hi') }
hi()  //undefined
      // Because the return value is console.log('hi'), the return value of console.log() is undefined, and hi is just the print value of console.log()
Copy the code

6. The call stack

1, concept,

(1) Before the JS engine calls a function, it needs to push the function’s environment into an array (push), which is called the call stack

(2) Before the JS engine exits a function, it needs to pop the environment from the call stack, and then return to the pop-up environment and continue to execute the subsequent code

2, for example,

console.log(1)  / / line 1
console.log('1+2 is equal to '. + add(1.2))   / / line 2
console.log(2)   / / line 3
Copy the code

3. Recursive Function (Factorial)

(1) factorial

function f(n){ return n ! = = 1? n* f(n-1) : 1 }Copy the code

(2) Understand recursion (3) Principle

  • Recursive functions usually call themselves
  • Recursive functions usually have a recursive exit, such as n = 1, and no longer call themselves
  • The process of transfer is actually pushing the stack
  • The process of regression is essentially a bouncing stack
  • If you recurse a few times, you’re going to push it a few times, so if you recurse four times, you’re going to push it four times

4. A call stack can be pushed a maximum of several times: the length of the call stack is limited

Chrome 12578 Firefox 26773 Node 12536 (Node and Chrome use V8 js engine, so similar) to measure the maximum number of calls to the stack

function computeMaxCallStackSize() {
try {
return 1 + computeMaxCallStackSize();
} catch (e) {
// This error indicates that stack overflow has overflowed
return 1; }}Copy the code

5, beyond the maximum stack times, will burst the stack, the program will crash

7. Function promotion

No matter where you declare the named function, it goes to the first line, right

add(1.2)
function add(x,y){return x+y}
/ / 3
The add function is defined because the named function actually runs to the first line. So I can say add(1,2)
Copy the code
let add=1
function add(x,y){return x+y}
// Error because the named function is in the first line, and add is the function name, then let wants to declare add is not allowed, add is already used. (Var is annoying, so don't use var.)
Copy the code
add(1.2)
let  fn = function (x,y){return x+y}
This function is not promoted because it is declared and assigned by let, and let does not allow (add (1,2)) to be declared first
Copy the code

8. Arguments and This (except for the arrow function)

1. How to view a functionthisandarguments

(1) First print this and arguments inside this function

 function fn(x) {
   console.log(arguments)
   console.log(this)}Copy the code

Call fn(); fn();

  • Visible,argumentsIs a pseudo-array containing all the normal arguments to the function
  • Each time a function is called, a corresponding argument is generated
  • We should try not to change arguments elements; changing arguments makes the code confusing

(3) to check this

  • Call this function, and thenthisAccording to the window
  • useFn. Call (x, 1, 2, 3), the first argument x is passed to this (which is automatically converted to an object), and the following arguments are passed toarguments
  • If I add to the code of PI (1)'use strict'It’s not automatically converted to an object

2. Arguments are normal arguments and this is a hidden argument

3. The process of understanding

A code

let person = {  // Declare a variable named person and assign an object to that variable, so that person holds the address of the object
  name: 'frank'.// This object has an attribute name with a value of Frank
  sayHi(){        
  console.log('Hello, my name is' + person.name)  // This object also has a function called sayHi, which prints the value of the name property of the person variable}}// The person variable holds the address of an object, so we can use this variable to get the properties of the object. That's what we've always known. This is called a reference
  Since we only defined the function sayHi, but did not call it, we can refer to the person variable when defining satHi, which is not fully declared. Because if this function had been called, the person variable would have already been declared.
  // The contents of a function must be declared when called, but it doesn't matter if they are declared when defined
Copy the code
let person = {
name: 'frank'.sayHi(){
console.log('Hello, my name is' + this.name) } }

person.sayHi()
Copy the code
  • We want the function to have a variable that points to an object that’s going to be created, and that object has a property that we need. That is, we want the function to be able to refer to an object
  • So when we define the function sayHi, it’s reallythisTreated as formal parameters (invisible) :sayHi(this){}
  • person.sayHi()The JS engine will make itperson.sayHi(person)
  • sopersonThe actual parameters,thisThat’s the formal parameter
  • sothis.name===person.name
  • There’s a variable in the functionthis, which points to the object to be createdpersonSo we canWith thisTo refer topersonAnd use its properties

4, function call upgrade!

(1) Small white call method (no longer allowed)

Person.sayhi () will automatically pass person to the function as the actual argument to this

(2) Master call method

person.sayHi.call(xxx)

  • The first argument XXX in () is the actual argument to the formal argument this
  • Such as a person

Five, start to understand functions again

(I) the actual definition of the function

Function name (invisible this, formal argument 1, formal argument 2) {return value}

(2) Aboutthis

  • thisIs a hidden argument to a function
  • In the new Fn() call, this refers to the newly generated object, which is determined by new

(3) The most correct method to call the function (the developer explicitly specifies this by call or apply)

Call (XXX, actual parameter 1, actual parameter 2)

Apply (XXX, [real parameter 1, real parameter 2])

  • XXX is the actual argument to the hidden parameter this
  • If this is not used in a function, write XXX asundefinedornulor'fuck'By default, this points to window, which is determined by the browser

(4) the nature of the previous function call method (JS implicitly pass this)

1. Function name (actual parameter 1, actual parameter 2)

  • Is equivalent toCall (undefined, actual parameter 1, actual parameter 2)
  • This is not used in the function, so write XXX asundefinedornullor'fuck'By default, this points to window, which is determined by the browser

2. Yyy. Function name (actual parameter 1, actual parameter 2)

`

  • Equivalent to ‘yyy. function name. call(yyy, actual parameter 1, actual parameter 2)
  • This points to YYy by default

(5) Examples

Let’s use this to write a forEach function that traverses arrays

Array.prototype.forEach2 = function(fn){  //forEach2函数是这样的:首先他需要接受个参数:函数fn
for(let i=0; i<this.length; i++){// Then he goes through the array
fn(this[i], i, this)   // the function fn is called every time, taking this[I], I, this as the actual parameters of fn}}Copy the code

Because we wrote this forEach into our array prototype, all arrays can call this function.

arr = [1.2.3]
arr.forEach2.call(arr,(x,y,z) = >{console.log(x,y,z)})
// Specify that arr is this
arr.forEach2((x,y,z) = >{console.log(x,y,z)})
// The browser itself thinks arr is this
arr.forEach2.call({0:'bb'.1:'cc'.length:2},(x,y,z) = >{console.log(x,y,z)})
// Specify that a pseudo-array is this
Copy the code

Bind the parameters of the function

1. Bind the function’s this with.bind

function f1(p1, p2){
console.log(this, p1, p2)
}
l
t f2 = f1.bind({name:'frank'})
// so f2 is the new function after f1 binds this
f2() Call ({name:'frank'})
Copy the code

2. Bind other parameters of the function with.bind

let f3 = f1.bind({name:'frank'}, 'hi')
f3() // f1.call({name:'frank'}, hi)
Copy the code

Arrow function

  • Arrow functions do not have their own this. The “this” inside the arrow function is the “this” outside the function, even if you call it. That’s great, never mind the annoying “this”
  • Arrow functions have no arguments
console.log(this) // This outside is window
let fn = () = > console.log(this)
fn() // window
fn.call({name:'frank'}) // window

let fn1 = () = > console.log(arguments)
fn3(1.2.3)
// Uncaught ReferenceError: arguments is not defined at fn1 
Copy the code

Execute the function immediately – the old way of generating local variables

  • In the ES5 era, in order to get local variables, you had to introduce a function
  • But if the function has a name, it also introduces a global function, which is more than worth the loss
  • So this function has to be anonymous
  • Declare an anonymous function, then immediately execute it with a ()
  • But the JS standard considers this syntax illegal
  • So JS programmers look for ways
  • It turns out that you can just add an operator in front of the anonymous function
  • ! , ~, (), +, – all work
  • But some of these operators go up
  • So it’s always recommended! To solve the
/ / recommend! ES5 old way
! function (){
var a =2
console.log(a)
} ()
Copy the code
// More recommended! ES6 latest method
{
    let a = 2
}
Copy the code
// Not recommended ()
console.log('hi')  // If the preceding line of the function is executed immediately
(function (){
var a =2
console.log(a)
} ()) Error: console.log(...) is not a function


// The following immediately executed function is put in front because the return in js does not make sense
undefined(function (){
var a =2
console.log(a)
} ()) // undefined is used as a function. Undefined is used as a function


// Remedy
console.log('hi');  // Put a semicolon between them. Note that this is the only case in JS where a semicolon is required between two lines of code!!
(function (){
var a =2
console.log(a)
} ())

Copy the code