Examples of JavaScript closures and javascript instances

Source: Internet
Author: User

Examples of JavaScript closures and javascript instances

I. Charging

1. Everything (reference type) is an object, and an object is a set of attributes.

2. A function is an object, but the function is not the same as an array-you can say that an array is an object, because an array is like a subset of an object. However, the relationship between a function and an object is not only a kind of the relationship between the function and the object. The relationship between the function and the object is complicated, and there is even a bit of logic between the function and the object.

Function Fn () {this. name = 'wang fupeng '; this. year = 1988;} var fn1 = new Fn (); var obj = {a: 10, B: 20}; equivalent to var obj = new Object (); obj. a = 10; obj. B = 20; var arr = [5, 'x', true]; equivalent to var arr = new Array (); arr [0] = 5; arr [1] = 'X'; arr [2] = true;

An object is created by a function, but a function is an object.

3. Each function has a property called prototype. The property value of this prototype is an object (set of attributes, which is emphasized again !), By default, there is only one attribute called constructor pointing to the function itself.

4. Each object has a _ proto _ attribute pointing to the prototype of the function that creates the object. This _ proto _ is a hidden attribute. JavaScript does not want developers to use this attribute. Some earlier Browsers Do not even support this attribute. Obj. _ proto __== Object. prototype

Ii. Closure

1. Basic concepts of closures

A function that has the right to access variables in another function scope. For example:

Function createComparisonFunction (propertyName) {return function (object1, object2) {// anonymous function value1 = object1 [propertyName]; value2 = object2 [propertyName]; if (value1 <value2) {return-1;} else if (value1> value2) {return 1 ;}else {return 0 ;}// create function var compareNames = createComparisonFunction ("name "); // call the var result = compareNames ({name: "Nicolas" },{ name: "Greg"}); // unreference the anonymous function (to release the memory) compareNames = null; alert (result); // 1

(1) benefits: it protects the security of variables in the function, enhances encapsulation, maintains a variable (cache) in the memory, anonymous self-executed functions, and simulates object-oriented programming.

(2 ). use Cases: Use closures to replace global variables; access parameters inside a function outside a function or in other functions; encapsulate related functions; and bind click events to nodes cyclically, use the value or node of the current loop in the event function, instead of the value or node of the last loop;

(3). Disadvantages: resident memory increases memory usage. improper use may easily lead to memory leakage. More importantly, improper use of closures may lead to invalid memory usage.

As long as the call to internal functions is possible, JavaScript needs to retain the referenced functions. In addition, when JavaScript is running, it is necessary to trace all the variables that reference this internal function. Until the last variable is discarded, the JavaScript Garbage Collector can release the corresponding memory space. The variables defined by the parent function are in the scope chain of the sub-function. If the sub-function is not destroyed, all the variables and functions in the scope chain will be maintained and will not be destroyed.

2. Use of closures

Closures have two purposes: one is to facilitate nested callback functions, and the other is to hide the details of objects.

For the former, the programming style of NodeJS can be explained, while the latter is invisible to the external part of the local variable inside the function, but the access function can be provided to access and modify the corresponding local variable, so as to realize the intention of OO encapsulation.

(1) A simple example

First of all, from a classic error, there are several divs on the page. We want to bind them with an onclick method, so we have the following code

<! DOCTYPE html PUBLIC "-// W3C // dtd xhtml 1.0 Transitional // EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

A very simple function is wrong. Every time alert outputs a value of 4, it is easy to make a simple modification.

$ (Document ). ready (function () {var spans =$ ("# divTest span"); for (var I = 0; I <spans. length; I ++) {(function (num) {// anonymous function expression spans [I]. onclick = function () {alert (num) ;}) (I); // execute now and pass the value of I to num }});

The code above will be executed after the page is loaded. When the value of I is 4, the judgment condition is not true and the for loop is executed completely, however, because the onclick method of each span is an internal function at this time, I is referenced by the closure, the memory cannot be destroyed, and the I value will always be 4, it will not be recycled until the program changes it or all the onclick functions are destroyed (the function is automatically assigned null or the page is uninstalled. In this way, every time we click span, The onclick function will look for the value of I (the scope chain is referenced), check that it is equal to 4, and then alert will give it to us. The second method is to use a function that is executed immediately and create a closure. When the function declaration is placed in parentheses, it becomes an expression, and the brackets are added to the brackets to call the function, when I is passed in, the function is executed immediately, and num stores the value of I each time.

(2) internal functions

Let's start with some basic knowledge. First, let's take a look at internal functions. An internal function is a function defined in another function. For example:

function outerFn () { function innerFn () {} } 

InnerFn is an internal function in the outerFn scope. This means that calling innerFn inside outerFn is valid, while calling innerFn outside outerFn is invalid. The following code causes a JavaScript error:

function outerFn() { document.write("Outer function<br/>"); function innerFn() { document.write("Inner function<br/>"); } } innerFn(); 

However, if innerFn is called within outerFn, the operation can be successful:

function outerFn() { document.write("Outer function<br/>"); function innerFn() { document.write("Inner function<br/>"); } innerFn(); } outerFn(); 

(3) Great Escape

JavaScript allows developers to pass functions like passing any type of data. That is to say, internal functions in JavaScript can escape defining their external functions.

There are many ways to escape. For example, you can specify an internal function to a global variable:

var globalVar; function outerFn() { document.write("Outer function<br/>"); function innerFn() { document.write("Inner function<br/>"); } globalVar = innerFn; } outerFn(); globalVar(); 

When outerFn is called, the global variable globalVar is modified. At this time, its reference is changed to innerFn. After that, globalVar is called and innerFn is called. At this time, calling innerFn directly outside outerFn will still cause errors, because although the internal function can escape by saving the reference in the global variable, however, the name of this function still exists only in the scope of outerFn.
You can also obtain internal function references by returning values from the parent function.

function outerFn() { document.write("Outer function<br/>"); function innerFn() { document.write("Inner function<br/>"); } return innerFn; } var fnRef = outerFn(); fnRef(); 

The global variable is not modified in outerFn, but a reference to innerFn is returned from outerFn. You can obtain this reference by calling outerFn, and the reference can be saved in the variable.

The fact that the internal function can still be called by referencing even if the function scope is left exists means that JavaScript needs to retain the referenced function as long as the internal function is called. In addition, when JavaScript is running, it is necessary to trace all the variables that reference this internal function. Until the last variable is discarded, the JavaScript Garbage Collector can release the corresponding memory space.

After talking about the closure for a long time, it is related to the closure. The closure refers to a function with the permission to access the variables of another function scope. A common way to create a closure is to create another function within a function, it is the internal function we mentioned above, so what we just mentioned is not nonsense, but also closure-related.

(4) SCOPE OF VARIABLES

Internal functions can also have their own variables, which are restricted to the scope of internal functions:

function outerFn() { document.write("Outer function<br/>"); function innerFn() { var innerVar = 0; innerVar++; document.write("Inner function\t"); document.write("innerVar = "+innerVar+"<br/>"); } return innerFn; } var fnRef = outerFn(); fnRef(); fnRef(); var fnRef2 = outerFn(); fnRef2(); fnRef2(); 

Whenever this internal function is called by reference or other means, a new innerVar variable is created, followed by 1, and finally displayed.

Outer functionInner function innerVar = 1Inner function innerVar = 1Outer functionInner function innerVar = 1Inner function innerVar = 1

Internal functions can also reference global variables like other functions:

var globalVar = 0; function outerFn() { document.write("Outer function<br/>"); function innerFn() { globalVar++; document.write("Inner function\t"); document.write("globalVar = " + globalVar + "<br/>"); } return innerFn; } var fnRef = outerFn(); fnRef(); fnRef(); var fnRef2 = outerFn(); fnRef2(); fnRef2(); 

Now the value of this global variable is continuously increasing every time you call an internal function:

Outer functionInner function globalVar = 1Inner function globalVar = 2Outer functionInner function globalVar = 3Inner function globalVar = 4

But what if this variable is a local variable of the parent function? Because internal functions reference the scope of the parent function (if you are interested, you can learn about the scope chain and activity object), internal functions can also reference these variables.

function outerFn() { var outerVar = 0; document.write("Outer function<br/>"); function innerFn() { outerVar++; document.write("Inner function\t"); document.write("outerVar = " + outerVar + "<br/>"); } return innerFn; } var fnRef = outerFn(); fnRef(); fnRef(); var fnRef2 = outerFn(); fnRef2(); fnRef2(); 

This time the results were very interesting and perhaps unexpected.

Outer functionInner function outerVar = 1Inner function outerVar = 2Outer functionInner function outerVar = 1Inner function outerVar = 2

We can see the effect of merging in the previous two cases. Calling innerFn through each reference will independently increase outerVar. That is to say, the second call of outerFn does not continue to use the value of outerVar, but creates and binds a new outerVar instance in the scope of the second function call. The two counters are completely irrelevant.

When an internal function is referenced outside its scope, a closure of the internal function is created. In this case, we call neither a local variable of an internal function nor a variable of its parameter as a free variable, and call an environment of an external function as a closed closure. Essentially, if an internal function references a variable in an external function, it is equivalent to authorizing the variable to be delayed. Therefore, when the external function is called, the memory of these variables will not be released (the last value will be saved), and closure still needs to use them.

(5) interaction between closures

When multiple internal functions exist, unexpected closures may occur. We define an incremental function. The increment of this function is 2.

function outerFn() { var outerVar = 0; document.write("Outer function<br/>"); function innerFn1() { outerVar++; document.write("Inner function 1\t"); document.write("outerVar = " + outerVar + "<br/>"); } function innerFn2() { outerVar += 2; document.write("Inner function 2\t"); document.write("outerVar = " + outerVar + "<br/>"); } return { "fn1": innerFn1, "fn2": innerFn2 }; } var fnRef = outerFn(); fnRef.fn1(); fnRef.fn2(); fnRef.fn1(); var fnRef2 = outerFn(); fnRef2.fn1(); fnRef2.fn2(); fnRef2.fn1(); 

Ing returns the reference of two internal functions. You can call any internal function through the returned reference. The result is as follows:

Outer functionInner function 1 outerVar = 1Inner function 2 outerVar = 3Inner function 1 outerVar = 4Outer functionInner function 1 outerVar = 1Inner function 2 outerVar = 3Inner function 1 outerVar = 4

InnerFn1 and innerFn2 reference the same local variable, so they share a closed environment. When innerFn1 is an incremental value of outerVar, a new start value of outerVar is set for innerFn2, and vice versa. We can also see that subsequent calls to outerFn will also create new instances of these closures, and will also create a new closed environment, essentially creating a new object, free variables are the instance variables of this object, and closures are the instance methods of this object, and these variables are also private, because they cannot be directly referenced outside the scopes that encapsulate them, this ensures the uniqueness of object-oriented data.

3. Simulate block-level scope

JavaScript is a function scope without block-level scope. No matter where the variables in the function are declared, they are visible to the entire function. That is, all the variables declared in the JavaScript function are pushed to the top of the function body, but they are declared in advance, the value assignment of the variable is still in the original position.

Anonymous functions can be used to simulate block-level scopes to avoid variables being declared as global variables in advance. the syntax of anonymous functions used as block-level scopes (usually called Private scopes) is as follows:

(Function () {// here is the block-level scope })();

For example:

function output(count){ (function(){ for(var i=0;i<count;i++){ alert(i); } })(); alert(i); } output(4); 

Any variables defined in anonymous functions will be destroyed at the end of execution. Therefore, variable I can only be used in a loop, and will be destroyed after use.

4. Private Variables

We call the public methods that have the right to access private variables and private functions as privileged methods.

(1) define privileged methods in Constructors

Function Person (name) {// name is the private variable this. getName = function () {// privileged method return name;}; this. setName = function (value) {// privileged method name = value};} var person = new Person ("zoumiao"); alert (person. getName (); person. setName ("zouzou"); alert (person. getName (); var person1 = new Person ("zou"); alert (person1.getName (); // "zou" alert (person. getName (); // "zouzou"

Defining privileged methods in constructors also has a disadvantage, that is, you must use the constructor mode to achieve this purpose, the disadvantage of the constructor mode is that the same group of new methods will be created for each instance. This problem can be avoided by using static private variables to implement privileged methods.

(2) Static private variables

You can also create a privileged method by defining private variables or functions in a private scope. The basic mode is as follows:

(Function () {var name = ''; // Static Property shared by all instances: Person = function (value) {// global constructor name = value ;} person. prototype. getName = function () {// public/privileged method return name;} Person. prototype. setName = function (value) {// public/privileged method name = value ;}}) (); var person = new Person ("zoumiao"); alert (person. getName (); person. setName ("zouzou"); alert (person. getName (); var person1 = new Person ("zou"); alert (person1.getName (); // "zou" alert (person. getName (); // "zou"

The difference between this mode and the privileged method defined in the constructor is that private variables and functions are shared by instances.

Related Article

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.