Closure concept: It means that in JavaScript, inner functions can always be accessed - parameters and variables declared in their local scope can still be accessed even after their local scope is destroyed.
Closure function: A function defined in the local scope.
The essence of closure: the local variables outside the closure function are resident in memory. (In the program, avoid using global variables, it is recommended to use private, encapsulated local variables)
Disadvantage: memory leak (any object still exists after you no longer need it).
Features of closures: 1. Functions are nested within functions; 2. Inner functions can reference outer parameters and variables; 3. Parameters and variables will not be recycled by the garbage collection mechanism.
The following 1 and 2 examples are for the understanding of the concept, the rest are some exercises, with the anonymous function self-execution in the next chapter, I hope you will have a deeper understanding of closures:
1. Access data outside the function inside the function
var a = 1; //global variable
function fn_01(){
alert(a);
}
fn_01(); //1 function fn_02(){ var num = 10; } fn_02() ; alert(num); //num is not defined //If the outside wants to access the local private variables inside the function, it cannot be accessed directly //Because the local variables will be destroyed after the function runs, which uses the closure. (The closure function can be accessed) 2. Access local variables through the closure function fn_01(){ var num = 3; //variable return function(){ //closure function return num; } }
alert( fn_01()() ); //The closure function accesses the variable in the local scope function fn_02(num){ //Parameter var num Formal parameter (formal parameter): The parameter that receives the data when the function is defined. Actual parameters (actual parameters): The parameters passed when calling the function. return function(){ //The closure function return num; } } alert( fn_02(4)() ); //The closure function accesses the parameters in the local scope
3. The value problem of the anonymous function in the loop
function fn_01(){
var arr = [];
for(var i = 0;i < 5;i++){
arr[i] = function(){ //The function is not executed , without taking the value of i outside, only assigning the function block to the array arr
return i;
}
}
return arr;
}
alert( fn_01() );
/*Explanation: The array arr loops 5 times and stores the function anonymous function in In the array, the function does not execute
function(){
return i;
},function(){
return i;
},function(){
return i;
},function(){
return i;
},function(){
return i;
}
*/
//自己执行
function fn_02(){
var arr = [];
for(var i = 0;i < 5;i++){
arr[i] = (function(){
return i;
})(); //让闭包函数自执行,每次执行,都将i存放在数组arr中
}
return arr;
}
alert( fn_02() ); //arr = [0,1,2,3,4];
//传参数
function fn_03(){
var arr = [];
for(var i = 0;i<5;i++){
arr[i] = (function(i){
return i;
})(i) //函数执行,返回循环每一次i的值,作为参数,传递给闭包函数,返回值i,传递给数组
}
return arr;
}
//alert(fn_04());
var list = fn_04();
for(var j = 0,len = list.length;j < len;j++){
alert(list[j]); //返回数组是[0,1,2,3,4]
}
//传参数加 闭包函数
function fn_04(){
var arr = [];
for(var i = 0;i<5;i++){
arr[i] = (function(i){ //闭包函数
return function(){ //闭包函数
return i;
};
})(i) //函数执行,返回循环每一次i的值,作为参数,传递给闭包函数,返回值i,传递给数组
}
return arr;
//此时arr数组存放的是function(){return i;}这个函数块 取值的时候,向上面的父级函数取i,这里的i传递的参数是循环变量每次的i
}
//alert(fn_04());
var list = fn_04();
for(var j = 0,len = list.length;j < len;j++){
alert(list[j]());
}
练习题 1. fn(1)(2)(3) 使用闭包得到6
function fn(x){
return function(y){
return function(z){
alert(x+y+z);
}
}
}
fn(1)(2)(3);
练习题 2.
var name = "jack";
var obj = {
name: "Lisa",
getName : function(){
return function(){ //闭包
return this.name;
}
}
}
alert( obj.getName()() );
var name = "jack";
var obj = {
name: "Lisa",
getName :function(){
var that = this; //this 指向obj
return function(){
return that.name;
}
}
}
alert( obj.getName()() );
练习题 3.三个数的累加,要求:同时支持下面两种写法
//sum(1)(2)(3) 使用闭包得到6
//sum(1,2,3);
var sum = (...a)=>{ //a表示所有的参数
if(a.length == 3;){
return a[0] + a[1] + a[2];
}else{
var x = a[0];
return function(y){
return function(z){
return x + y + z;
}
}
}
}
alert( sum(1,2,3) );
alert( sum(1)(2)(3) );
练习题 4.点击按钮,让按钮里面的值++
<style type="text/css">
#btn{
width:80px;
height:30px;
font-size: 16px;
}
</style>
<input type="button" value="0" id="btn"/>
var oBtn = document.getElementById("btn")
oBtn.onclick = function(){
this.value = Number(this.value) + 1;
}
//闭包写法实现
(function(){
var i = Number(oBtn.value);
oBtn.onclick = function(){
this.value = ++ i;
}
})() //减少全局变量
function fn_06(){
var i = 0;
return function(){
return ++ i;
}
}
var n = fn_06();
oBtn.onclick = function(){
this.value = n();
}
//循环加计时器--闭包解决
for (var i=1; i<=9; i++) {
setTimeout( function timer(){
console.log( i );
},1000 );
}
/*解释 i = 0 ...覆盖 1,2,3,4
setTimeout(function(){console.log(i);},0) //计时器,是延时操作,即使事件是0,也排在后面执行(异步)
setTimeout(function(){console.log(i);},0)
setTimeout(function(){console.log(i);},0)
setTimeout(function(){console.log(i);},0)
setTimeout(function(){console.log(i);},0)
最后 i = 5 不执行下面了, 所以输出5个5 */
//闭包解决
for (var i=1; i<=9; i++) {
(function(j){
setTimeout( function timer(){
console.log( j );
}, 1000 );
})( i );
}
//let 也可以解决(详解可以看前几章关于for循环中有关let的解释)
for(let i = 0;i < 5;i ++){
setTimeout(function(){
console.log(i);
},0)
}
/* i=0
setTimeout(function(){console.log(i);},0)
i=1
setTimeout(function(){console.log(i);},0) .....i=2 i=3 i=4 */
这是 一道面试题,如何更改下面的代码,将a[6] 输出的结果得到6 ?
var a=[];
for(var i=0;i<10;i++){
a.push(
function(){console.log(i)}
);
}
a[6](); //10
var a=[];
for(let i=0;i<10;i++){
a.push(
function(){console.log(i)}
);
}
a[6](); // 6
var a=[];
for(var i=0;i<10;i++){
a.push(
function(i){
return function(){
console.log(i);
}
}(i)
);
}
a[6](); //6