


JavaScript Advanced Programming (3rd Edition) Study Notes 9 js Function (Part 2)_Basic Knowledge
Then let's look at functions - magical objects.
9. Function as value
In general programming languages, if you want to use a function as a value, you need to use a function pointer or proxy. Implementation, but in ECMAScript, a function is an object that has all the characteristics of a general object. In addition to a function having its own properties and methods, it can also be used as a reference type value. In fact, our previous example We have already used functions as the value of an object attribute. For example, a function can also be used as a parameter or return value of another function. The callback function in asynchronous processing is a typical usage.
var name = 'linjisong';
var person = {name:'oulinhai'};
function getName(){
return this.name;
}
function sum(){
var total = 0,
l = arguments.length;
for(; l; l--)
{
total = arguments[l-1];
}
return total;
}
// Define the function that calls the function, using the function as the formal parameter
function callFn(fn,arguments,scope){
arguments = arguments || [];
scope = scope || window;
return fn.apply(scope, arguments);
}
// Call callFn, using the function as the actual parameter
console.info(callFn(getName));//linjisong
console.info(callFn(getName,'',person));//oulinhai
console.info(callFn(sum,[1,2,3,4]));//10
Look at another typical example of using a function as a return value. This example comes from Chapter 5 of the original book:
function createComparisonFunction(propertyName) {
return function(object1, object2){
var value1 = object1[propertyName];
var value2 = object2[ propertyName];
if (value1 < value2){
return -1;
} else if (value1 > value2){
return 1;
} else {
return 0;
}
};
}
var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29 }];
data.sort(createComparisonFunction("name"));
console.info(data[0].name); //Nicholas
data.sort(createComparisonFunction ("age"));
console.info(data[0].name); //Zachary
10. Closure (Closure)
A closure is a function that has access to a variable in the scope of another function. Objects are data with functions, and closures are functions with data.
First, a closure is a function, and then a closure is a function with data. So, what data does it carry? Let's look at the example of function as return value. What is returned is an anonymous function. As this anonymous function is returned, the outer createComparisonFunction() function code is executed. According to the previous conclusion, the outer function The execution environment will be popped off the stack and destroyed, but in the subsequent sorting, you can see that the propertyName in the scope of createComparisonFunction() can still be accessed in the returned anonymous function, which shows that although the execution environment corresponding to createComparisonFunction() has been destroyed , but the active object corresponding to this execution environment has not been destroyed, but is used as an object in the scope chain of the returned anonymous function. In other words, the data contained in the closure composed of the returned anonymous function is: The corresponding activity object of the outer function. Since the properties of the active object (that is, the variables, functions and formal parameters defined in the outer function) will change as the code of the outer function is executed, the data contained in the closure composed of the anonymous function that is finally returned is the outer layer The active object after the function code execution is completed, which is the final state.
I hope you can understand the above paragraph carefully and understand it again and again. Although I have tried my best to make it easier to understand, the concept of closure is still a bit abstract. Let's take a look at an example. This example comes from Chapter 7 of the original book:
function createFunctions(){
var result = new Array();
for (var i=0 ; i < 10; i ){
result[i] = function(){
return i;
};
}
return result;
}
var funcs = createFunctions();
for (var i=0,l=funcs.length; i < l; i ){
console.info(funcs[i]());// Each function outputs 10
}
Here, since the data contained in the closure is the final state of the active object corresponding to createFunctions, and after the createFunctions() code is executed, the attribute i of the active object has become 10, so each of the following calls returns All functions output 10. To deal with this problem, you can use anonymous function scope to save the state:
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i ){
result[ i] = (function(num){
return function(){
return num;
};
})(i);
}
return result;
}
Save each state using an anonymous function that is called immediately (saved in the active object corresponding to the anonymous function), and then when the final returned function is called, it can be closed through The data contained in the package (the data in the corresponding anonymous function activity object) is accessed correctly, and the output result becomes 0,1,...9. Of course, by doing this, 10 closures will be created, which will have a greater impact on performance. Therefore, it is recommended not to abuse closures. In addition, because closures will save active objects of other execution environments as part of their own scope chain loop, which may also cause memory leaks. Although closures have hidden dangers in efficiency and memory, the function of closures is too powerful. Let's take a look at the applications of closures - first, let's go back to the function binding method bind() mentioned yesterday.
(1) Function binding and currying
A. Look at this again, first an example (Chapter 22 of the original book):
If you click the "Hello" button, what will be printed on the console? It turned out to be a Button, not the expected Event. The reason is that when the button is clicked, the internal property this of the handler function points to the button object. You can use closures to solve this problem:
btn.onclick = function(event){
handler.handleClick(event);//Form a closure, the object handler is the one who calls the function, the internal attribute this of the function points to the handler object, so Event will be output}
B. The above solution is not elegant. There is a new function binding method bind() in ES5. We use this method to rewrite it:
if(!Function.prototype.bind){//bind is new in ES5. In order to ensure normal operation, it is not supported when Add this method on your browser
Function.prototype.bind = function(scope){
var that = this;//The function object that calls the bind() method
return function(){
that.apply(scope, arguments);//Use the apply method to specify the internal property of the that function object this
};
};
}
btn.onclick = handler.handleClick.bind( handler);//When using the bind() method, you only need to use one statement
In the bind() method added here, the main technology is to create a closure to save the parameters during binding As the internal attribute this when the function is actually called. If you are not sure whether the browser itself supports bind() or our bind() works here, you can remove the conditional judgment of feature detection and try changing the method name.
C. When using the bind() method for the function above, only the first parameter is used. If multiple parameters are passed in when calling bind() and the second parameter is used as the parameter when the function is actually called, Then we can bind default parameters to the function.
if(!Function.prototype.bind){
Function.prototype.bind = function(scope){
var that = this;//The function object that calls the bind() method
var args = Array.prototype.slice.call(arguments,1);//Array of parameters starting from the 2nd parameter
return function(){
var innerArgs = Array.prototype.slice.apply (arguments);
that.apply(scope, args.concat(innerArgs));//Use the apply method, specify the internal property this of the that function object, and fill in the parameters passed in when binding
};
};
}
D. Currying: When binding above, the first parameter is used to set the internal attribute this when the function is called. If all The parameters during binding are all used as pre-filled parameters, which is called function currying.
if(!Function.prototype.curry){
Function.prototype.curry = function(){
var that = this;//The function object that calls the curry() method
var args = Array.prototype.slice.call(arguments);//Pre-filled Parameter array
return function(){
var innerArgs = Array.prototype.slice.apply(arguments);//Parameter array when actually called
that.apply(this, args.concat(innerArgs)) ;//Use the apply method and add pre-filled parameters
};
};
}
(2) Use closure cache
Also Remember the function that used recursion to implement the Fibonacci sequence? Use the closure cache to rewrite it:
var fibonacci = ( function(){//Use closure cache, recursion
var cache = [];
function f(n){
if(1 == n || 2 == n){
return 1;
}else{
cache[n] = cache[n] || (f(n-1) f(n-2));
return cache[n];
}
}
return f;
})();
var f2 = function(n){//Do not use closure cache, recurse directly
if(1 = = n || 2 == n){
return 1;
}else{
return f2(n-1) f2(n-2);
}
};
The following is the test code and the running results on my machine:
var test = function(n){
var start = new Date().getTime();
console.info(fibonacci(n));
console.info( new Date().getTime() - start);
start = new Date().getTime();
console.info(f2(n));
console.info(new Date().getTime() - start);
};
test(10);//55,2,55,2
test(20);//6765,1,6765,7
test(30);//832040,2,832040,643
It can be seen that the larger the n value, the more obvious the advantage of using cache calculation. As an exercise, you can try modifying the function that calculates the factorial yourself.
(3) Imitate block-level scope
In ECMAScript, there are statement blocks, but there is no corresponding block-level scope, but we can use closures to imitate block-level scope. , the general format is:
(function(){
//Here is the block statement
})();
The above pattern is also called an immediately called function expression. This pattern has become very popular, especially due to jQuery Source code has become popular on a large scale using this method.
Closures also have many interesting applications, such as imitating private variables and private functions, module patterns, etc. We will not discuss them here for now. We will look at these contents after deeply understanding the object.
Regarding functions, let’s talk about these first. There are many excellent articles on the Internet. If you are interested, you can search and read them yourself. Here is an article recommended, a translation by the translator of "JavaScript Advanced Programming (3rd Edition)": Exploring Named Function Expressions.

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

Both Python and JavaScript's choices in development environments are important. 1) Python's development environment includes PyCharm, JupyterNotebook and Anaconda, which are suitable for data science and rapid prototyping. 2) The development environment of JavaScript includes Node.js, VSCode and Webpack, which are suitable for front-end and back-end development. Choosing the right tools according to project needs can improve development efficiency and project success rate.
