Home Web Front-end JS Tutorial JavaScript Advanced Programming (3rd Edition) Study Notes 9 js Function (Part 2)_Basic Knowledge

JavaScript Advanced Programming (3rd Edition) Study Notes 9 js Function (Part 2)_Basic Knowledge

May 16, 2016 pm 05:49 PM

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.

Copy code The code is as follows:

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:
Copy code The code is as follows:

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:
Copy code The code is as follows:

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:
Copy code Code As follows:

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):
Copy code The code is as follows:


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:
Copy code The code is as follows:

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:
Copy the code The code is as follows:

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.
Copy code The code is as follows:

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.
Copy code The code is as follows:

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:
Copy the code The code is as follows:

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:
Copy the code The code is as follows:

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:
Copy code The code is as follows:

(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.
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat Commands and How to Use Them
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How do I create and publish my own JavaScript libraries? How do I create and publish my own JavaScript libraries? Mar 18, 2025 pm 03:12 PM

Article discusses creating, publishing, and maintaining JavaScript libraries, focusing on planning, development, testing, documentation, and promotion strategies.

How do I optimize JavaScript code for performance in the browser? How do I optimize JavaScript code for performance in the browser? Mar 18, 2025 pm 03:14 PM

The article discusses strategies for optimizing JavaScript performance in browsers, focusing on reducing execution time and minimizing impact on page load speed.

What should I do if I encounter garbled code printing for front-end thermal paper receipts? What should I do if I encounter garbled code printing for front-end thermal paper receipts? Apr 04, 2025 pm 02:42 PM

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

How do I debug JavaScript code effectively using browser developer tools? How do I debug JavaScript code effectively using browser developer tools? Mar 18, 2025 pm 03:16 PM

The article discusses effective JavaScript debugging using browser developer tools, focusing on setting breakpoints, using the console, and analyzing performance.

Who gets paid more Python or JavaScript? Who gets paid more Python or JavaScript? Apr 04, 2025 am 12:09 AM

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

How do I use source maps to debug minified JavaScript code? How do I use source maps to debug minified JavaScript code? Mar 18, 2025 pm 03:17 PM

The article explains how to use source maps to debug minified JavaScript by mapping it back to the original code. It discusses enabling source maps, setting breakpoints, and using tools like Chrome DevTools and Webpack.

The difference in console.log output result: Why are the two calls different? The difference in console.log output result: Why are the two calls different? Apr 04, 2025 pm 05:12 PM

In-depth discussion of the root causes of the difference in console.log output. This article will analyze the differences in the output results of console.log function in a piece of code and explain the reasons behind it. �...

TypeScript for Beginners, Part 2: Basic Data Types TypeScript for Beginners, Part 2: Basic Data Types Mar 19, 2025 am 09:10 AM

Once you have mastered the entry-level TypeScript tutorial, you should be able to write your own code in an IDE that supports TypeScript and compile it into JavaScript. This tutorial will dive into various data types in TypeScript. JavaScript has seven data types: Null, Undefined, Boolean, Number, String, Symbol (introduced by ES6) and Object. TypeScript defines more types on this basis, and this tutorial will cover all of them in detail. Null data type Like JavaScript, null in TypeScript

See all articles