This is the 20th day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021

preface

Today when reviewing the ES6 part, I saw the function expression and the recursion part, and felt quite a lot. I would like to share it with you. The function declaration and function expression should be distinguished from each other.

Functional expression

Functional expressions, while more powerful, are also more confusing. As we know, there are two ways to define functions: function declarations and function expressions. The function declaration looks like this :\

Function functionName (arg0,arg1,arg2){// The key feature of function declarations is that function declarations are promoted, that is, function declarations are defined before code is executed. This means that a function declaration can appear after the code that calls it: sayHi (); Function sayHi (){console. log (" Hi!" );Copy the code

This example does not throw an error because the JavaScript engine reads the function declaration before executing the code. The second way to create functions is through function expressions. Function expressions take several different forms, the most common being this: Let functionName = function (arg0,arg1,arg2){} Function expressions look like a normal variable definition and assignment, that is, create a function and assign it to a variable functionName. The function created in this way is called anonymous funtion because there is no long identifier after the function keyword. (Anonymous functions are sometimes also called Lamda functions). The name attribute of an anonymous function that is not assigned to another variable is a null string. Function expressions, like any other expression in JavaScript, need to be assigned before being used. The following example causes an error:

sayHi(); 1/Error! function doesn ' texist yet let sayHi = function (){ console . log (" Hi !" ); aCopy the code

The key to understanding the difference between a function declaration and a function expression is to understand promotion. For example, the result of executing the following code might be unexpected :\

// Don't do that! if ( condition ){ function sayHi (){ console . log (' Hi ! '); else { function sayHi (){ on console . log (' Yo ! ');Copy the code

This code looks normal, except that if condition is true, the first sayHi () definition is used; Otherwise, use the second one. In fact, this is not a valid syntax in ECAMScript. The JavaScript engine will try to correct this into a proper declaration. The problem is that browsers are inconsistent in the way they correct this problem. Most browsers will ignore condition and return the first declaration. Firefox returns the first declaration if condition is true. This is dangerous, so don’t use it. However, if we replace the above function declaration with a function expression, we can do just fine:

// Let sayHi; If (condition){sayHi = function (){console. log (" Hi! ); }else {sayHi = function () console. log (" Yo!" ); }Copy the code

As expected, this example assigns a function to the variable sayHi based on the value of condition. The ability to create functions and assign values to variables can also be used to return another function as a value in one function:

function createComparisonFunction ( propertyName ) return function (object1,object2)( let value1=object1[ propertyName ]; let value2=object2[ propertyName ]; if (value1<value2){ return -1; ) else if ( valuel >value2){ return1;) else { return 0; }Copy the code

The createComparisonFunction () function here returns an anonymous function that is either assigned to a variable or can be called directly. But inside createComparisonFunction (), that function is anonymous. Any time a function is used as a value, it is a function expression. As we’ll see later in this chapter, this is not the only way to use functional expressions.

recursive

Recursive functions usually take the form of a function calling itself by name, as shown in the following example:

 function factorial ( num ){ 
 if ( num <=1){ 
return1; 
} else {
 return num * factorial ( num -1);
 }
Copy the code

This is a classic recursive factorial function. This is fine, but if you assign this function to another variable, you get a problem:

let anotherFactorial = factorial ; factorial = null ; console . log ( anotherFactorial (4)); / / an errorCopy the code

Here we save factorial () in another variable, anotherFactorial, and set factorial to 1NUL1, leaving only a reference to the original function. When you call anotherFactorial (), you recursively call actorial0), but because it’s no longer a function, you get an error. Using arguments.callee when writing recursive functions avoids this problem. Arguments.callee is just a pointer to the executing function, so it can be called recursively inside the function as follows:

 function factorial ( num ){ if ( num <=1){
 return 1; else {
 return num * argumentB . callee ( num -1);
 }

Copy the code

Replacing the function name with arguments.callee, as in the bold line here, ensures that no matter what variable is used to call the function, there will be no problem. So when writing recursive functions, arguments.callee is the preferred reference to the current function. However, code running in strict mode does not have access to arguments.callee because accessing it would cause an error. In this case, you can do this by using named function expression. Such as:

Const factorial =(function fo(num){if (num <=1 at {return 1; else { return Dumf ( num -1) ); }Copy the code

 

Here we create a named function expression fo and assign it to the variable factorial. Even if you assign a function to another variable, the name of the function expression, £, remains the same, so recursive calls are not a problem. This mode can be used in both strict and non-strict modes.