A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
闭包的原理? lexical scoping
闭包是基于词法作用域写代码所产生的自然结果
Closures are functions that have access to the variables that are present in their scope chain even if the outer function ceases to exist.
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。
By definition, closure is a combination of a function that remembers its global variable. When the function is called Javascript creates execution context which is a specification that contains information of all variables and properties. It is called lexical environment.
Normally, a lexical environment goes to void when the execution context is removed from the execution context stack. However, there is an exception to it. It is still accessible as long as it is reachable from another execution context.
This unique behaviour enables the nested function to access its outer variable after the function is called.
This tackles the problem coming from placing variables on the very global level of codes. When variables are declared at the global level, there is a possibility that one has the same name as another which will cause the application to crash, or malfunction. Closure ensures that the declared variables are secure from such issues.
example:
var add = (function () {
var counter = 0;
return function () {
counter += 1;
return counter;
}
})();
add();
add();
add();// the counter is now 3
Practical Usage:
Closures are useful because they let you associate some data (the lexical environment) with a function that operates on that data. This has obvious parallels to object-oriented programming, where objects allow us to associate some data (the object's properties) with one or more methods.
Consequently, you can use a closure anywhere that you might normally use an object with only a single method.
Situations where you might want to do this are particularly common on the web. Much of the code we write in front-end JavaScript is event-based — we define some behavior, then attach it to an event that is triggered by the user (such as a click or a keypress). Our code is generally attached as a callback: a single function which is executed in response to the event.
闭包里怎么用setTimeout?
1.使用IIFE传参创建闭包
由于setTimeout异步执行的特性,所以定义一个IIFE先把i的值传入进来,避免在执行setTimeout的时候i的值变为4
for (var i=0; i<5; i++) {
(function (j) {
setTimeout(() => console.log(i),1000*j)
})(i)
}
2.块作用域let
隔一秒输出一个数:
for (let i=0; i<5; i++) {
setTimeout(() => console.log(i),1000*i)
}
用setTimeout写一个倒计时输出5,4,3,2,1
for (let i=5; i>0; i--) {
setTimeout(() => console.log(i),1000*(5-i))
}
闭包:实现外部作用域访问内部作用域的变量的方法。得益于函数可以作为参数或者返回值,将内部函数传递到所在的词法作用域以外,它会持有对原始定义作用域的引用。
闭包为什么会导致作用域链不释放?如果有变量引用闭包所返回的函数,那个这个函数将不会释放,同时也使原始作用域不会得到释放。除非不再有引用,才会释放。
如果去掉了所有闭包功能,会出现什么问题?
应用场景:创建私有变量,柯里,防抖节流
缺点:内存泄漏
There are two main disadvantages of overusing closures:
-The variables declared inside a closure are not garbage collected. 闭包是不回收引用的那个对象还是不回收整个外部作用域,怎么验证这一点?
-Too many closures can slow down your application. This is actually caused by duplication of code in the memory.