JavaScript Advanced Programming (3rd Edition) Learning notes 9 JS function (next) _ Basics

Source: Internet
Author: User
Tags anonymous closure
And then look at the function--the object with the magic color.

9, as a function of the value

In a general programming language, if you want to use a function as a value, you need to implement it like a function pointer or an agent, but in ECMAScript, a function is an object that has all the characteristics of a generic object, except that the function can have its own properties and methods, can also be used as a reference type value, in fact, we have in the previous example of a function as an object property value, and for example, the function can also be used as a parameter or return value of another function, the callback function in asynchronous processing is a typical use.

Copy Code code 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;
}

Defines a function that calls a function, using a function as a formal argument
function Callfn (fn,arguments,scope) {
arguments = Arguments | | [];
Scope = Scope | | Window
return fn.apply (scope, arguments);
}
Call CALLFN, using a function as the actual argument
Console.info (CALLFN (GetName));//linjisong
Console.info (CALLFN (GetName, ', person '));//oulinhai
Console.info (CALLFN (sum,[1,2,3,4));//10

Let's look at a typical example of using a function as a return value, which comes from chapter 5th of the original book:
Copy Code code 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, the closure is a function, then the closure is a function with data, then, what is the data? We look up the function as an example of the return value, and return an anonymous function, and as the anonymous function is returned, the outer createcomparisonfunction () function code is executed, and the execution environment of the outer function is ejected and destroyed as the previous conclusion. But the next sort can see that the PropertyName in the createcomparisonfunction () scope can still be accessed in the returned anonymous function, which means that although createcomparisonfunction () The corresponding execution environment has been destroyed, but the active object of the execution environment is not destroyed, but rather as an object in the scope chain of the returned anonymous function, in other words, the closed package of the returned anonymous function contains data that is the corresponding active object of the outer function. Because the properties of the active object (that is, the variables, functions, and formal parameters defined in the outer function) vary with the execution of the outer function's code, the resulting closure of the returned anonymous function contains data that is the active object, the final state, after the execution of the outer function code.

Hope to understand the above paragraph, and repeatedly understand. Although I have done what I can describe as easier to understand, but the concept of closure is still somewhat abstract, let's look at an example from the original book, Chapter 7th:
Copy Code code as follows:

function Createfunctions () {
var result = new Array ();
for (Var i=0 i < 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] ())//Every function output 10
}

Because the data in the closure is createfunctions the final state of the corresponding active object, and after the Createfunctions () code executes, the active object's property I has become 10, so every function returned in the following call outputs 10. To handle this problem, you can use an anonymous function scope to save the state:
Copy Code code as follows:

function Createfunctions () {
var result = new Array ();
for (Var i=0 i < i++) {
Result[i] = (function (num) {
return function () {
return num;
};
}) (i);
}
return result;
}

Each state is saved by using an anonymous function that is called immediately (stored in the corresponding active object of the anonymous function). Then, when the returned function is invoked, it can be accessed correctly through the data enclosed by the packet (the data in the corresponding anonymous function activity object), and the output turns into 0,1,... 9. This, of course, creates 10 closures that have a significant performance impact, so it is not recommended to abuse closures, and it can also cause memory leaks because closures save the active objects of other execution environments as part of their own scope chain. While closures are inefficient and memory-insecure, the closures are too powerful to look at the closure applications-first let's go back to what we said yesterday about the functional binding method bind ().

(1) Function binding and Gerty (currying)

A, look at this again, first look at an example (the original book, chapter 22nd):
Copy Code code as follows:

<button id= ' my-btn ' title= ' button ' >Hello</button>
<script type= "Text/javascript" >
var handler = {
Title: ' Event ',
Handleclick:function (event) {
Console.info (This.title);
}
};
var btn = document.getElementById (' my-btn ');/Get Page button
Btn.onclick = handler.handleclick;//Add event handler function to page button
</script>

If you click the "Hello" button, what does the console print? It's a button, not an event in the expectation, because this is where you click the button, the Process function internal property This points to the button object. You can use closures to solve this problem:
Copy Code code as follows:

Btn.onclick = function (event) {
Handler.handleclick (event);//form a closure, the function is called the object handler, the function internal property this point to the handler object, so will output event}

B, the above solution is not elegant, the new function binding method in ES5 bind (), we use this method to rewrite:
Copy Code code as follows:

if (! Function.prototype.bind) {//bind is new in ES5, adding this method on unsupported browsers to ensure normal operation
Function.prototype.bind = function (scope) {
var that = this;//calls the Bind () method's function object
return function () {
That.apply (scope, arguments);//Use the Apply method to specify the internal properties of that function object.
};
};
}
Btn.onclick = Handler.handleClick.bind (handler);//Use the Bind () method with only one statement

In the bind () method added here, the main technique is also to create a closure that holds the parameters of the binding as the intrinsic property of the function when it is actually called. If you're not sure if the browser itself supports bind () or if we have bind (), you can get rid of the condition of the feature check and try it again with a different method name.
C, when the face function uses the bind () method, only the first argument is used, and if bind () is passed in more than one argument and the 2nd argument is started as a parameter when the function is actually called, then we can bind the function to the default argument.
Copy Code code as follows:

if (! Function.prototype.bind) {
Function.prototype.bind = function (scope) {
var that = this;//calls the Bind () method's function object
var args = Array.prototype.slice.call (arguments,1);//array of arguments starting with the 2nd argument
return function () {
var Innerargs = Array.prototype.slice.apply (arguments);
That.apply (Scope, Args.concat (Innerargs))//Use the Apply method to specify the internal property of that function object, and the parameters passed in when the binding is filled
};
};
}

D, Corrie: In the above binding time, the first parameter is used to set the function call when the internal properties this, if all the binding parameters as a pre-filled parameter, then called the function of Gerty.
Copy Code code as follows:

if (! Function.prototype.curry) {
Function.prototype.curry = function () {
var that = this;//calls the function object of the curry () method
var args = Array.prototype.slice.call (arguments);//pre-filled parameter array
return function () {
var Innerargs = Array.prototype.slice.apply (arguments);//Actual call time parameter array
That.apply (This, Args.concat (Innerargs))//Use the Apply method and add the pre-filled parameters
};
};
}

(2) Using closure caching

Remember the previous function of using recursion to implement the Fibonacci sequence? Use the closure cache to overwrite:
Copy Code code as follows:

var Fibonacci = (function () {//using closure cache, recursive
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) {//no closure cache used, direct recursion
if (1 = = N | | | 2 = n) {
return 1;
}else{
return F2 (n-1) + F2 (n-2);
}
};

Here is the test code and the results of my machine running:
Copy Code code 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

As you can see, the greater the N value, the more obvious the advantage of using caching calculations. As an exercise, you can try to modify the function of calculating the factorial yourself.

(3) Mimic block-level scopes

In ECMAScript, there are statement blocks, but there are no corresponding block-level scopes, but we can use closures to mimic block-level scopes, in general format:
Copy Code code as follows:

(function () {
This is a block statement.
})();

The above pattern is also called a function expression called immediately, and this pattern is already very popular, especially since the jquery source is used in this way.
Closures also have a lot of interesting applications, such as imitating private variables and private functions, module patterns, and so on, which are not discussed here, and look at them after you have a deep understanding of the objects.

On the function, say this first, there are a lot of great articles on the Internet, interested in their own search to read. Here we recommend an article, "JavaScript Advanced Programming (3rd edition)" A translator's translation: The name function Expression Quest.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.