美文网首页JavaScript < ES5、ES6、ES7、… >
JavaScript的三座大山----作用域和闭包

JavaScript的三座大山----作用域和闭包

作者: 小伙子太认真 | 来源:发表于2019-02-16 23:39 被阅读154次

    相信很多学习前端的朋友都认识JavaScript的三座大山。

    这里假设阅读的朋友对js已经有一定的基础。如果没有的话,请暂时留步。

    那js三座大山是什么呢?

    1、原型和原型链

    2、作用域和闭包

    3、异步和单线程

    作用域和闭包基本上是每个学习前端的必经之路,也是必须聊的一个话题。

    那么接下来就来聊聊作用域和闭包

    那就问题来了

    第一个问题:什么是作用域?作用域分为什么?

    作用域分为全局作用域和局部作用域,这里只讨论ES6之前的,因为ES6有了块级作用域概念了。说实话作用域可以延伸出来其他的概念,比如作用域链、预处理机制。提到的话我会说明一下。现在就以作用域和闭包这两大主体作为线索展开。

    全局作用域:定义在window对象下,在window定义的变量可以被局部作用域使用。

    局部作用域:定义在函数内部。声明的变量,只能在函数内部使用。

    来看看几个例子就明白,这个还是比较简单的。

    第一个例子证明:在全局作用域下无法访问局部作用域

    思考一个问题:为什么函数内部打印的结果的未定义?

    第二个例子证明:在局部作用域的变量可以访问全局作用域的变量

    思考:函数内部打印结果是什么?为什么?函数外部打印的结果为什么为2?

    第三个例子证明:有var声明的才是变量,不然在函数内部是改变参数值。

    小帖士:下面分别是两个例子,需要分开执行。

    思考:对比两个例子,为什么最后打印的都是1?为什么第一次函数内部打印的结果是未定义?

    先埋一下伏笔哈!在文章最后我都会一一解答,这里是想让你思考这些问题,让你们自己思考出来印象会更深刻。不会也没关系,请听我娓娓到来。或者如果实在想知道答案,直接拉到最后。

    接下来有请我们今天另外一位嘉宾:闭包先生

    闭包先生是我们JavaScript的一员,也是贡献比较多的一员,相传他有一门绝学:定义在函数内部的函数,能够使函数内部和外部进行链接。

    引用权威的一句话:JavaScript中的函数在定义他们的作用域运行,而不是在执行它们的作用域里运行。

    其他博客这么说:指有权访问另一个函数作用域的变量的函数。

    是不是一头雾水?哈哈!刚开始接触我也是一头雾水,那就用实例说话

    第一个问题:闭包是什么已经给出答案了。例子的话等会跟下面一个问题一起给。

    第二个问题:闭包的优缺点?

    思考:闭包的优点有哪些?缺点先放一边

    来讲一下这个过程吧!我们知道fn1函数执行之后,返回的是fn2函数名,为了调用fn2函数的话需要加一个()。而每次执行完函数fn2之后,变量都会加1,并且会存储在fn1函数的局部作用域中。先前说的什么是闭包这个问题,就是定义在函数里面的函数,在外部能够访问函数内部的变量,但是我们知道访问变量只沿着作用域链向上查找,不能向下。所在可以在函数内部定义一个函数,将变量传到定义的函数里面(指fn2),再通过return函数名的方式将fn1函数里面的变量访问到。

    上面说到作用域链也随便说一下,不深入剖析。

    什么是作用域链?

    上面的例子就可以说明:fn2的局部作用域---->fn1的局部作用域--->window全局作用域

    在这里我给你抛出一个问题:能不能改变作用域链的大小?(这篇文章就不说了)

    接下来就解决之前给你们抛出去的几个问题,想到了想不到看我的见解和你的讲解是否有分歧?

    问题一:为什么函数内部打印的结果的未定义?

    这个就要请出我们的导演啦!(js预解析机制

    很多刚学习js的同学都会有疑惑,为什么不是打印不是1?我们js有他的运行机制,先预解析,再逐行运行代码。

    那么问题来了,预解析过程在做什么?

    原来我们的js中,预解析是提升声明变量,怎么个提升法?

    提升函数里面的变量们就变成这个样子了。将var a;提到函数顶部,所以访问不到全部变量

    问题二:函数内部打印结果是什么?为什么?函数外部打印的结果为什么为2?

    打印结果是1,原因是在函数内部打印的时候,函数内部还没有这个变量,因为也没有存在变量提升的情况,所以会向全局变量伸出他的魔爪。找到全局变量a= 1;函数内部还是会继续执行,将a赋值为2之后,再函数外部打印自然也就是2啦!

    问题三:对比两个例子,为什么最后打印的都是1?为什么第一次函数内部打印的结果是未定义?

    就是有参数的情况下,函数内部和参数一样的变量名都代表参数。

    问题四:闭包的优缺点

    优点:有利于封装函数,能够访问局部变量

    缺点:占用内存和内存泄漏问题

    好了,就到这里了,有问题的欢迎下方留言。一起学习,有一句话想了好久,在我遇到瓶颈的时候就会告诉自己:“别人也会遇到,如果我解决了,我才能追上他们。“

    相关文章

      网友评论

        本文标题:JavaScript的三座大山----作用域和闭包

        本文链接:https://www.haomeiwen.com/subject/iibieqtx.html