1、闭包的概念
闭包是函数的一种高级应用方式。闭包通过建立一个不被销毁的存储空间,在函数的外部调用和使用函数内部的数据。
2、闭包的特点
(1)函数作用域不会被销毁
优点:空间中的内容永远存在
缺点:占用大量的内存空间
(2)可以从函数外部访问函数内部的变量
优点:使用变量数据方便
缺点:容易泄露数据
(3)保护私有作用域变量
优点:确保私有作用域变量一直存在
缺点:占用内存空间
3、闭包的定义(也属于条件,缺一不可)
(1)定义一个函数a,返回值是一个函数b
(2)在返回值函数b中,使用函数a定义的局部作用域变量
(3)在函数a的外部引用函数a,并执行返回值函数b
4、闭包的简单代码
//定义一个函数a
function a(){
let x = 'a 函数中的 x'
let y = 'a 函数中的 y'
let z = 'a 函数中的 z'
//返回值是一个函数b
return function b(){
//在返回值函数b中,使用函数a定义的局部作用域变量 x y z
let res = {str1:x,str2:y,str3:z}
return res
}
}
//在函数a的外部引用函数a,并执行返回值函数b
let a1 = a()
let a2 = a1()
console.log(a2)
// 控制台输出为 {str1: "a 函数中的 x", str2: "a 函数中的 y", str3: "a 函数中的 z"}
5、闭包的应用
举个简单的例子,当点击li标签时得到相应的数字,我们就可以在循环绑定过程中使用闭包 。
<ul>
<li>我是第 一 个li标签</li>
<li>我是第 二 个li标签</li>
<li>我是第 三 个li标签</li>
<li>我是第 四 个li标签</li>
<li>我是第 五 个li标签</li>
</ul>
<script>
// 获取所有的li标签
let lis = document.querySelectorAll('li')
// 通过for循环遍历lis里所有标签
for(let i = 0; i < lis.length; i++){
// 给li标签绑定点击事件,使用自执行函数
lis[i].addEventListener('click',(function (int) {
return function () {
console.log(int+1)
}
})(i))
}
</script>
最终效果如下:
6、简单的过去了,直接来道经典面试题,一起看看吧
function fun(n,o){
console.log(o)
return {
fun:function(m){
return fun(m,n)
}
}
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1); c.fun(2); c.fun(3);
问:三行输出分别是什么?
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
先看 var a = fun(0),把 0 传入 fun(n,o) 中,那么 n = 0,o = undifine
而 fun(n,o) return 了 { fun:function(m) { returnfun(m,n) } }
所以 a 就等于 { fun:function(m) { return fun(m,0) } }
所以 a.fun(1) = function(1) { return fun(1,0) } = fun(1,0),输出 0
同样 a.fun(2) = function(2) { return fun(2,0) } = fun(2,0),输出 0
以此类推,a.fun(3) 输出 0
所以最终输出的结果为:undifine,0,0,0
var b = fun(0).fun(1).fun(2).fun(3);
fun(0) 输出 undifine
fun(0).fun(1) = a.fun(1) = fun(1,0) = { fun:function(m) { return fun(m,1) } } ,输出 0
fun(0).fun(1).fun(2) = function(2) { return fun(2,1) } = fun(2,1) = { fun:function(m) { return fun(m,2) } },输出 1
以此类推,fun(0).fun(1).fun(2).fun(3),输出 2
最终按次序输出的是:undifine,0,1,2
var c = fun(0).fun(1); c.fun(2); c.fun(3);
var c = fun(0).fun(1),根据以上的推理,输出的是 undifine,0
c = { fun:function(m) { return fun(m,1) }} ,c.fun(2) = function(2) { return fun(2,1) },输出 1
c.fun(3) = function(3) { return fun(3,1) },输出 1
所以第三行输出的是:undifine,0, 1, 1
最后的答案是:
第一行:undifine,0,0,0
第二行:undifine,0,1,2
第三行:undifine,0,1,1
希望读者能通过本文对闭包现象有进一步的了解,如有其它见解或看法,欢迎指正或留言讨论。