Introduction
In many traditional languages (C/C/Java/C#, etc.), functions exist as second-class citizens. You can only declare a function using language keywords and then call it. If you need to use the function as a parameter To pass it to another function, assign it to a local variable, or use it as a return value, you need to go through special methods such as function pointer and delegate.
In the JavaScript world, functions are first-class citizens. They not only have all the ways of using traditional functions (declaration and calling), but can also assign values, pass parameters, and return like simple values. Such functions are also called third-class functions. First-class Function. Not only that, the function in JavaScript also acts as the constructor of the class and is an instance of the Function class. Such multiple identities make JavaScript functions very important.
1. Entry-level JavaScript functions
Like other languages, JavaScript functions follow the principle of declaration first and use later. Function names can only contain letters, numbers, underscores or $, and cannot start with numbers. There are two common ways to declare functions:
Note that there are subtle differences between the above two methods of function declaration: the first method is a named function when declared, whether it is declared before the call, after the call, or even in a position that will not be executed (such as return statement or in a branch that will never be true), are accessible in the entire scope; the second way is by assigning an anonymous function to a variable, which is not strictly a function declaration (function declaration ) is a function expression. This function cannot be accessed by any code before assignment, which means that the assignment must be completed before calling, otherwise an error will occur when calling: "TypeError: undefined is not a function ". For example:
Functions in JavaScript can handle variable-length parameters. Inside the function, there is a local variable named arguments, which is an array-like object that contains all the parameters passed in when called. The length attribute indicates the number of parameters. For example:
2. Advanced JavaScript functions
2.1 Anonymous functions and nested functions
In JavaScript, you can declare a function without a name, called an anonymous function. At the same time, JavaScript also allows functions to be declared inside functions, called nested functions. The scope of a nested function is the entire parent function.
In the previous function declaration section, we saw a use of anonymous functions and nested functions. Since anonymous functions have no names, they will not introduce new variables to pollute the context, and will bring new variable scopes. Therefore, anonymous functions are often is used to prevent global environmental pollution.
There is a special global environment (global object) in the JavaScript runtime. This object stores global functions and variables. In actual development, several third-party libraries or multiple js files are often used. If you accidentally introduce duplication in the global object Variable or function declaration will cause confusion in code execution. For example, two js files are introduced one after another, and each defines its own function log for internal use. The second introduced function will overwrite the first definition and will not throw any errors. Calling the log function in subsequent executions may cause problems. causing errors. At this time, using an anonymous function to wrap the logic in the entire js can avoid this error. This method has been used by most open source js libraries.
The above code is a simple example. The scope of the log function is limited to this anonymous function, and the anonymous function is surrounded by a pair of parentheses () outside to form a function expression. The expression The value is a function, followed by a pair of parentheses to indicate that the function will be executed immediately, allowing the original code to be executed normally. However, functions declared in this way, variables declared via var, etc. are internal and cannot be accessed by any code other than anonymous functions. If you need to expose some functions as interfaces, there are several methods:
2.2 High-order Function
If a function is used as a parameter or return value, it is called a higher-order function. All functions in JavaScript can be used as higher-order functions. This is also a characteristic of the first type of function. Below we will analyze these two usage methods respectively.
The above code shows an example of passing a function as a parameter into another function process call. In the implementation of the process function, the callback is treated as a black box, responsible for passing the parameters to it, and then getting the return value. The specific implementation of callback was not clear before. Only when lines 20 and 22 are executed, the callback is represented by negative or square respectively, and the opposite or square value operation is performed on each element respectively.
The above code shows an example of using a function as a return value. generator is a natural number generator function, and the return value is a natural number generator function. Each time the generator is called, an anonymous function is returned as the result. This anonymous function returns each natural number in turn when it is actually called. The variable i in the generator will increase by 1 every time this anonymous function is called. This is actually a closure. Let’s introduce closures below.
2.3 Closure
Closure (Closure) is not a new concept. Closures are used in many functional languages. In JavaScript, closures are used when you use variables within the scope of an external function within an inline function. Use a common analogy to explain the relationship between closures and classes: classes are data with functions, and closures are functions with data.
One characteristic of variables used in closures is that they are not released when the parent function returns, but end when the closure life cycle ends. For example, like the generator example in the previous section, gen1 and gen2 use independent variables i (when i of gen1 increases by 1, i of gen2 is not affected, and vice versa), as long as gen1 or gen2 If the two variables are not garbage collected by the JavaScript engine, their respective variable i will not be released. In JavaScript programming, closures are used unconsciously. While this feature of closures brings ease of use, it can also easily cause problems like memory leaks. For example:
The function of this code is to display the label name of a node when it is clicked. It registers an anonymous function as a click event processing function of a DOM node. A DOM object elem is referenced in the function, forming a closed Bag. This will generate a circular reference, namely: DOM-> Closure->DOM-> Closure... The DOM object will not be released before the closure is released; and the closure serves as the event handling function of the DOM object exists, so the closure will not be released before the DOM object is released. Even if the DOM object is deleted in the DOM tree, due to the existence of this circular reference, neither the DOM object nor the closure will be released. You can avoid this memory leak by using the following method:
In the above code, this is used instead of elem (in the DOM event handling function, the this pointer points to the DOM element itself), so that the JS runtime no longer thinks that the variable of the parent class is used in this function, so a closure is no longer formed. .
Closures will also bring about many similar memory leak problems. Only pay attention to closures when writing code to try to avoid such problems.
2.4 Class Constructor
JavaScript functions also serve as constructors of classes, so as long as you declare a function, you can use the new keyword to create an instance of the class.
The above constructor is quite special, it has a return statement, so what objects do obj1~obj4 point to respectively? The actual result is this:
The specific reason is explained in this article, and I will not go into details in this article. Since the constructor with a return value will produce strange results, do not call a return statement with a return value in the constructor (an empty return is fine).
3. JavaScript function monster level
Welcome to the monster-level function teaching area, where we will teach you how to face monsters calmly and comfortably. . .
3.1 Function class
There is a built-in class called Function in the JavaScript runtime. Declaring a function with the function keyword is actually a shorthand form of creating a Function class object. All functions have all the methods of the Function class, such as call, apply, and bind. Wait, you can verify this statement through the instanceof keyword.
Since Function is a class, its constructor is Function (itself is also an object of the Function class), and it should be possible to generate a function object through the new keyword. Here comes the first monster, which is how to construct a function using the Function class. The syntax of Function is as follows:
Among them, arg1, arg2, ... argN are strings, representing parameter names, and functionBody is also a string, representing the function body. The previous parameter names can be more or less. The constructor of Function will treat the last parameter as In the function body, the previous ones are treated as parameters.
The above method constructs a function through Function. This function is exactly the same as other functions declared with the function keyword.
Seeing this, many people may ask why such a monster is needed? "Whatever exists is reasonable." The Function class has its unique use. You can use it to dynamically generate various function logic, or replace the function of the eval function, and keep the current environment from being polluted*.
3.2 Self-update Function
In many languages, once a function is declared, it cannot declare a function with the same name again, otherwise a syntax error will occur. However, functions in JavaScript can not only be declared repeatedly, but also update themselves. The monster that eats itself is here!
Summary
JavaScript functions are very powerful. While they solve many problems beautifully, they also bring about many negative problems. The usage of monster-level functions is usually some little-known usage. Do not use it lightly unless it is particularly necessary. Otherwise, it will make it difficult to read the code and affect the team's development efficiency.
* Strict mode is introduced in the new ECMAScript. In strict mode, the eval function is greatly restricted, and it can also ensure that the environment is not polluted
Have you understood it, friends? It is very practical. If there is anything missing, please ask the experts for guidance and we can make progress together