JavaScript闭包(必考三座大山之二)

Posted 精通各种hello world的小希

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript闭包(必考三座大山之二)相关的知识,希望对你有一定的参考价值。

在开始写这篇文章之前,首先我要跟大家说一下,闭包是前端开发必考的题目,不考的话有两个原因,第一可能出题面试官忘了,第二这家公司的面试官可能没什么水平。

作用域和自由变量

所谓万丈高楼平地起,盘龙卧虎高山齐,在进入闭包的学习之前,我们先要去了解一下作用域的概念,只能说真正理解作用域才能更好地学习闭包,通俗来讲,作用域就是在定义的变量在某个范围内是可使用的一个区域。

 简单地画了个图,上述的框框我们可以看出,其实作用域就是某个变量可使用的合法范围,比如变量a,作为全局作用域,是公开使用的,不论是函数外部还是fn1,2,3都可以使用,就好比公厕这种地方是面向全社会人员的。我们再看看fn3,假如fn2,fn1或者函数外部需要使用或者修改a3这个变量,是无法使用的。

 在这里顺便讲一下自由变量,自由变量就是一个变量在当前作用域没有定义,但被使用了,我们再来看看这张图

这个代码段的执行顺序是,先调用fn1()、fn2()、fn3() ,当执行fn3()的时候,返a + a1 + a2 + a3,因为在fn3()的作用域没有a2,a1,a所以要往上一层fn2寻找,fn2没有a1,a所以再往上一层fn1找,fn1没有a,所以最后要到全局作用域才能找到a。因为a2,a1,a不在fn3的作用域范围,所以它们可称为自由变量

再啰嗦多一句,如果全局作用域都没找到的变量,则会报错——xx is not defined

闭包

上述的讲解同学们应该可以了解到了作用域到底是神马东西了,那么闭包这玩意,其实就是作用域的特殊情况,它有两种表现:

1.函数作为参数传递

2.函数作为返回值返回

我们先看看两个代码片段

// 函数作为返回值
        function fun (){
            const a = 100;
            return function(){
                console.log(a);//100
            }
        }
        const fn = fun();
        const a = 200;
        fn();
 // 函数作为参数被传递
        function print(fn){
            const a = 200;
            fn();
        }
        const a = 100;
        function fun (){
            console.log(a);//100
        }
        print(fun);

 解释一下控制台的打印结果,为什么是100呢,上面的内容已经讲解到,自由变量往往不存在当前的作用域范围中,所以需要一层一层地往上寻找,console.log(a)里面的变量a在函数中未被定义,所以需要往上一层寻找自己被定义和赋值的地方。

闭包的应用

我们先看一个代码片段

 // 闭包隐藏数据,只提供API
        function Cache(){
            // 闭包中的数据被隐藏,不被外界访问
            const data = {};
            return{
                set: function(key,val){
                    data[key] = val
                },
                get: function(key){
                    return data[key]
                }
            }
        }
        const t = Cache()
        t.set('money',100)
        console.log(t.get('money'));//100

上述代码中,我们简单做了一个Cache工具,在函数返回值返回两个函数,set用于传值,get用于取值,最后在控制台中打印出100。那我们能不能直接修改data的值?

 // 闭包隐藏数据,只提供API
        function Cache(){
            // 闭包中的数据被隐藏,不被外界访问
            const data = {};
            return{
                set: function(key,val){
                    data[key] = val
                },
                get: function(key){
                    return data[key]
                }
            }
        }

        data.b = 200 //控制台会报错

相信同学们已经知道为什么data.b = 200不可行吧,原因就是作用域问题,data是在Cache函数的作用域中,作用域外面并不能获取到它的值。所以这里函数主要的功能是只提供API,那么闭包中的data数据则由它自己来管理,外界无法修改。

今天你学废了吗?

 

以上是关于JavaScript闭包(必考三座大山之二)的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript异步(必考三座大三之三)——第二集:event loop

JavaScript原型和原型链(必考三座大三之一)

JavaScript异步(必考三座大山之三)——第四集:async-await

理解JS的三座大山

闭包漫谈(从抽象代数及函数式编程角度)

林森---博客园之二,对《闭包》的个人见解!希望能帮到不理解闭包的同学们!