闭包的定义:
闭包是JavaScript中,函数的一种高级应用方式
在了解闭包之前,我们需要知道函数的定义作用域和执行作用域
function box(){
function fn(){
console.log("我是fn函数")
}
fn();
// fn的执行作用域,是box的局部作用域
}
// box的定义作用域,是全局作用域
// fn的定义作用域,是box的局部作用域
box();
// box的执行作用域,是全局作用域
fn(); //执行不了
function fun(){
box();
// box的执行作用域,是fun的局部作用域
}
函数执行时会开辟一个执行空间, console.log(“我是fn函数”)这段代码就是在这个空间中执行,当代码执行完毕后,这个空间就被销毁了
然后我们再看下面的代码:
function box(){
function fn(){
}
return fn;
}
var f = box();
f();
// 当前变量f,其实就是box内部的fn,的执行作用域,就变成了全局
在box中返回了一个函数,返回值被变量f保存,因为函数也是对象,简单赋值属于浅拷贝,那么其实当前的f就是box中返回的那个函数的一个引用,如果将f作为函数执行了,相当于执行了box返回的那个函数的引用,其实就是执行了box里面的函数
总结:
函数的定义作用域,是固定的,写在哪就是哪
函数的执行作用域,是可变的,在哪执行就是哪
函数在执行时,可以拿到当前函数所在定义作用域中的所有数据
了解了以上的内容后,其实也就了解的闭包的大部分内容。我们再看下面两段代码,比较不同之处。
function box(){
var a = 10;
a++;
console.log(a);
}
box(); // 11
box(); // 11
======================================
function box(){
var a = 10;
function fn(){
a++;
console.log(a);
}
return fn;
}
var f = box();
f(); //11
f(); //12
看到这里其实就已经产生了闭包,那么到底什么是闭包呢?
闭包:利用函数的嵌套,实现将第一层函数中的局部变量,可以在第一层函数外部修改的过程就叫闭包。
闭包的总结:
1.有一个函数A,在函数A内部返回一个函数B
2.在函数B中访问函数A的私有作用域变量即私有变量
(私有变量:函数内部的变量,在外部修改)
3.在函数A外部,有变量引用函数B
闭包并不是一种固定写法,而是一种场景,只要满足了以上三个条件,缺一不可,就是闭包
闭包的特点:
既是优点也是缺点
1.作用域空间不销毁
2.可以通过闭包语法,从外部访问函数内部的变量
3.保护私有变量
4.解决掉所有的全局变量,节省内存空间
我们也可以换种方式理解,闭包就好像是电脑上的回收站。
硬盘即存储空间,删除数据,先转到某个空间中(回收站),可以找回来
内存即运行空间,删除数据,直接删除,找不回来
闭包就是利用作用域的嵌套,触发计算机的垃圾回收机制让执行空间不销毁,提升函数作用域的生命周期。
闭包:就是利用作用域的嵌套,将局部变量进化成私有变量的环境
最后我们再来看闭包的几个常用场景
闭包的应用场景:
1.循环中的事件,事件处理函数中使用了循环的每次的计数器
var ali = document.querySelectorAll(".list li");
for(var i=0;i<ali.length;i++){
ali[i].onclick = (function(index){
return function(){
console.log(index);
}
})(i);
}
2.给某些系统默认的回调函数,传参
//给计时器的回调函数,传参
function fn(a){
return function(){
console.log(a);
};
}
setTimeout(fn("CSDN"), 1000);
3.模块化开发
var f = (function(){
var a = "hello";
function fn(){
console.log(a + "world");
}
return fn;
})();
f();