Closures have become a near-mythical concept, very important, difficult to grasp, and difficult to define. This article starts with the definition of closure
ancient definition
A closure means that function variables can be kept in the function scope, so it seems that the function "wraps" the variable
So a function containing a variable is a closure
//According to the old definition, the function foo containing the variable n is a closure function foo() { var n = 0; } console.log(n)//Uncaught ReferenceError: n is not defined
Definition one
A closure is a function that has access to its scope
In this case, functions that need to look up variables through the scope chain are closures
//According to definition 1, the function foo() that needs to find the variable n in the global environment through the scope chain is the closure var n = 0; function foo() { console.log(n)//0 } foo();
Definition 2
A closure is a function that has access to a variable in the scope of another function
In this case, the inner function that accesses the scope of the upper function is a closure
//According to definition 2, the bar function nested in the foo function is a closure function foo(){ var a = 2; function bar(){ console.log(a); // 2 } bar(); } foo();
Definition three
A closure is a function that is called outside the scope of the function declaration
Calling a function outside the scope of the function declaration requires passing the function as a return value or as a parameter
【1】Return value
//According to definition 3, declared in the scope of the foo() function, the bar() function called in the scope of the global environment is a closure function foo(){ var a = 2; function bar(){ console.log(a); //2 } return bar; } foo()();
It can be abbreviated as follows:
function foo(){ var a = 2; return function(){ console.log(a);//2 } } foo()();
【2】Parameter
//According to definition 3, declared in the scope of the foo() function, the baz() function called in the scope of the bar() function is a closure function foo(){ var a = 2; function baz(){ console.log(a); //2 } bar (bases); } function bar(fn){ fn(); }
So, by whatever means, as long as the inner function is passed outside the lexical scope in which it is located, it will hold a reference to the original scope, and the closure will be used wherever the function is executed
IIFE
Is IIFE a closure?
The foo() function is defined in the global scope and is called immediately in the global scope, which is a closure according to definition 1. If according to definition 2 and definition 3, it is not a closure
var a = 2; (function foo(){ console.log(a);//2 })();
Another more important reason is that before the appearance of requireJS, the implementation of modular programming was mainly through IIFE, and the common operation in IIFE is to expose the interface through window.fn = fn, and this fn is the closure, and IIFE is only A function call containing a closure
(function(){ var a = 0; function fn(){ console.log(a); } window.fn = fn; })() fn();
finally
The reason why the definition of closure is confusing, I think it has to do with different interpretations of classic books. The classic definition is the original words of the rhinoceros book, and the second definition is the original words of the elevation
However, it can be summed up as a few conditions that a function needs to satisfy in order to become a closure
Strictly speaking, a closure needs to meet three conditions: [1] access to the scope where it is located; [2] function nesting; [3] to be called outside the scope where it is located
Some people think that only condition 1 is satisfied, so IIFE is a closure; some people think that only conditions 1 and 2 are satisfied, so the nested function is a closure; some people think that all three conditions are satisfied, so A function that is called outside the scope is a closure