search
HomeWeb Front-endJS TutorialJavaScript 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.

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 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 result[i] = function(){
return i;
};
}
return result;
}

var funcs = createFunctions();
for (var i=0,l=funcs.length; 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 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
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
From C/C   to JavaScript: How It All WorksFrom C/C to JavaScript: How It All WorksApr 14, 2025 am 12:05 AM

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.

JavaScript Engines: Comparing ImplementationsJavaScript Engines: Comparing ImplementationsApr 13, 2025 am 12:05 AM

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.

Beyond the Browser: JavaScript in the Real WorldBeyond the Browser: JavaScript in the Real WorldApr 12, 2025 am 12:06 AM

JavaScript's applications in the real world include server-side programming, mobile application development and Internet of Things control: 1. Server-side programming is realized through Node.js, suitable for high concurrent request processing. 2. Mobile application development is carried out through ReactNative and supports cross-platform deployment. 3. Used for IoT device control through Johnny-Five library, suitable for hardware interaction.

Building a Multi-Tenant SaaS Application with Next.js (Backend Integration)Building a Multi-Tenant SaaS Application with Next.js (Backend Integration)Apr 11, 2025 am 08:23 AM

I built a functional multi-tenant SaaS application (an EdTech app) with your everyday tech tool and you can do the same. First, what’s a multi-tenant SaaS application? Multi-tenant SaaS applications let you serve multiple customers from a sing

How to Build a Multi-Tenant SaaS Application with Next.js (Frontend Integration)How to Build a Multi-Tenant SaaS Application with Next.js (Frontend Integration)Apr 11, 2025 am 08:22 AM

This article demonstrates frontend integration with a backend secured by Permit, building a functional EdTech SaaS application using Next.js. The frontend fetches user permissions to control UI visibility and ensures API requests adhere to role-base

JavaScript: Exploring the Versatility of a Web LanguageJavaScript: Exploring the Versatility of a Web LanguageApr 11, 2025 am 12:01 AM

JavaScript is the core language of modern web development and is widely used for its diversity and flexibility. 1) Front-end development: build dynamic web pages and single-page applications through DOM operations and modern frameworks (such as React, Vue.js, Angular). 2) Server-side development: Node.js uses a non-blocking I/O model to handle high concurrency and real-time applications. 3) Mobile and desktop application development: cross-platform development is realized through ReactNative and Electron to improve development efficiency.

The Evolution of JavaScript: Current Trends and Future ProspectsThe Evolution of JavaScript: Current Trends and Future ProspectsApr 10, 2025 am 09:33 AM

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

Demystifying JavaScript: What It Does and Why It MattersDemystifying JavaScript: What It Does and Why It MattersApr 09, 2025 am 12:07 AM

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

See all articles

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)
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
1 months agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.