Home  >  Article  >  Web Front-end  >  Understand and use JavaScript’s closure mechanism_Basic knowledge

Understand and use JavaScript’s closure mechanism_Basic knowledge

WBOY
WBOYOriginal
2016-05-16 15:45:12877browse

The great Comrade Einstein once said: "If you can't explain something clearly to a 6-year-old child, then you don't understand it yourself." However, when I explained what closures were to a 27-year-old friend, I failed completely.

This was originally a question raised by a foreign friend on Stack Overflow about JavaScript closures. However, since this question was asked on Stack Overflow, of course many experts will come out to answer it. Some of the answers are indeed classics, such as the following one:

If you define an internal function in an external function, that is, a function nested function, then the internal function can also access the variables in the external function:

function foo(x) {
 var tmp = 3;
 function bar(y) {
 alert(x + y + (++tmp));
 }
 bar(10);
}

foo(2); // alert 16
foo(2); // alert 16
foo(2); // alert 16

This code can be executed correctly and returns the result: 16, because bar can access the variable tmp of the external function and can also access the parameter x of the external function foo. But the above example is not a closure!

To implement closure, the internal function needs to be returned as the return value of the external function. Before returning, the internal function will lock all the variables in the external function that have been accessed in the memory. In other words, these variables It will reside in the memory of bar and will not be recycled by the garbage collector, as follows:

function foo(x) {
 var tmp = 3;
 return function (y) {
 alert(x + y + (++tmp));
 }
}
var bar = foo(2); // bar 现在是个闭包了
bar(10); // alert 16
bar(10); // alert 17
bar(10); // alert 18

In the above code, when bar is executed for the first time, the result will still be returned: 16, because bar can still access x and tmp, although it no longer directly exists in the scope of foo. So since tmp is locked in the closure of bar, tmp will be incremented every time bar is executed, so when bar is executed for the second and third times, 17 and 18 are returned respectively.

In this example, x is just a pure value. When foo is called, the value x will be copied to foo as a parameter.

But when JavaScript handles objects, it always uses references. If you call foo with an object as a parameter, then what is passed in foo is actually a reference to the original object, so the original object is also equivalent to being closed. , as follows:

function foo(x) {
 var tmp = 3;
 return function (y) {
 alert(x + y + tmp++);
 x.memb = x.memb ? x.memb + 1 : 1;
 alert(x.memb);
 }
}
var age = new Number(2);
var bar = foo(age); // bar 现在是个闭包了
bar(10); // alert 15 1
bar(10); // alert 16 2
bar(10); // alert 17 3

As expected, every time bar(10) is executed, not only tmp is incremented, but x.memb is also incremented, because x in the function body and age outside the function refer to the same object.

via http://stackoverflow.com/questions/111102/how-do-javascript-closures-work

Supplement: Through the above examples, you should be able to understand closures more clearly. If you think you understand it, you can try to guess the execution result of the following code:

function foo(x) {
 var tmp = 3;
 return function (y) {
 alert(x + y + tmp++);
 x.memb = x.memb ? x.memb + 1 : 1;
 alert(x.memb);
 }
}
var age = new Number(2);
var bar1 = foo(age); // bar1 现在是个闭包了
bar1(10); // alert 15 1
bar1(10); // alert 16 2
bar1(10); // alert 17 3

var bar2 = foo(age); // bar2 现在也是个闭包了
bar2(10); // alert ? ?
bar2(10); // alert ? ?
bar2(10); // alert ? ?

bar1(10); // alert ? ?
bar1(10); // alert ? ?
bar1(10); // alert ? ?

When used in practice, closures can create very elegant designs, allowing customization of the various calculation methods defined on funarg. The following is an example of array sorting, which accepts a sorting condition function as a parameter:

[1, 2, 3].sort(function (a, b) {
 ... // 排序条件
});

The same example is that the map method of an array maps the original array to a new array based on the conditions defined in the function:

[1, 2, 3].map(function (element) {
 return element * 2;
}); // [2, 4, 6]

Using functional parameters, you can easily implement a search method and support unlimited search conditions:

someCollection.find(function (element) {
 return element.someProperty == 'searchCondition';
});

There are also application functions, such as the common forEach method, which applies the function to each array element:

[1, 2, 3].forEach(function (element) {
 if (element % 2 != 0) {
  alert(element);
 }
}); // 1, 3

By the way, the apply and call methods of function objects can also be used as application functions in functional programming. Here, we think of them as application functions - functions applied to parameters (in apply it is the parameter list, in call it is an independent parameter):

(function () {
 alert([].join.call(arguments, ';')); // 1;2;3
}).apply(this, [1, 2, 3]);

Closures have another very important application - delayed calling:

var a = 10;
setTimeout(function () {
 alert(a); // 10, after one second
}, 1000);
还有回调函数:

//...
var x = 10;
// only for example
xmlHttpRequestObject.onreadystatechange = function () {
 // 当数据就绪的时候,才会调用;
 // 这里,不论是在哪个上下文中创建
 // 此时变量“x”的值已经存在了
 alert(x); // 10
};
//...

You can also create encapsulating scopes to hide helper objects:

var foo = {};

// 初始化
(function (object) {

 var x = 10;

 object.getX = function _getX() {
  return x;
 };

})(foo);

alert(foo.getX()); // 获得闭包 "x" – 10

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