JavaScript 的闭包简单解析

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),根据以上的推理,输出的是 undifine0
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

希望读者能通过本文对闭包现象有进一步的了解,如有其它见解或看法,欢迎指正或留言讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值