闭包,关于闭包用途

1. JS中变量的作用域

在理解闭包之前,我们得弄清楚JS中变量的作用域原理,它分为全局作用域和局部作用域,它有一个特点就是局部可以获取全局的声明变量,而全局却不能得到局部声明的变量,我们先来看一个小例子:

                                     var num = 1902;

                                     function methods() {

                                       var qty = 25;

                                       console.log(num);

                                     }

                                     methods();  // 1902
  
                                     console.log(qty);  // 报错,找不到 qty 变量;

当然在局部声明变量的时候一定要用var或者let,不然会在全局生成一个变量,容易照成全局污染,上面代码如果qty没有var声明:

                                    var num = 1902;

                                    function methods() {

                                        qty = 25;

                                        console.log(num);

                                     }

                                     methods();  // 1902;

                                     console.log(qty);  // 25;

2.什么是闭包

那么现在问题来了,如果我们非要从外部来读取局部变量中的声明变量呢,寻常方式不行,我们可以变通一下,就是在函数内部再嵌套一个函数,然后返回这个嵌套函数:

                                           function methods() {

                                                 var qty = 25;

                                                 return function num() {

                                                 console.log(qty);

                                                }
  
                                             }

                                            var num1 = methods();

                                            num1()  // 25

这样,控制台就会打印出 qty 变量的值了,其实在上面的代码中,被返回的函数 num()就产生了闭包,由于在js中,只有函数内部的子函数才能读取局部变量,所以可以把闭包理解成定义在一个函数内部的函数,简单的说,JavaScript允许使用内部函数:即函数定义和函数表达式位于另一个函数的函数体内而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

3.闭包的用途

我们接着探讨闭包的表达形式以及用途。
(1)匿名自执行函数

                                         (function () {
                                            var methods = function () {
                                                console.log('执行完函数后销毁')
                                            };
                                            methods();
                                        })();

上面代码也是闭包的应用,运用于函数只会执行一次的场景,执行完便会被释放。
(2)给对象设置私有变量

                                      var result = function () {
                                             var count = 1;
                                             return function () {
                                                  count++;
                                                  console.log(count)
                                              }
                                        }()
                                          result(); // 2
                                          result(); // 3
                                          result(); // 4
                                          result(); // 5

上面代码可以保存自己的私有变量,防止代码之间的冲突。
(3)异步执行函数
下面先看一个小例子:

                                      for (var i = 0; i < 5; i++) {
                                              console.log(i);  //0,1,2,3,4
                                      }
                                      for (var i = 0; i < 5; i++) {
                                             setTimeout(() => {
                                                     console.log(i); //5,5,5,5,5
                                            }, 0)
                                      }

为什么会出现上述差异呢,原因在于setTimeout是异步加载,所以为先循环结束后输出最后结果,如果我们就是想实现输出0,1,2,3,4呢。那就要用到闭包了:

                                          for (var i = 0; i < 5; i++) {
                                                (function (i) {
                                                      setTimeout(() => {
                                                            console.log(i); //0,1,2,3,4
                                                      }, 0);
                                                })(i);
                                            }

上面就是异步调用闭包,它可以让变量值始终保存在内存中,即使外部的执行环境已经结束了。

4.闭包的优缺点

(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  •   函数表达式是 JavaScript 中的一个既强大有容易令人困惑的特性。定义函数的的方式有两种: 函数声明; ...
    霜天晓阅读 835评论 0 1
  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,869评论 2 9
  • 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。 一、变量...
    风萧萧易水寒_1196阅读 265评论 0 0
  • 1 概述 1.1函数的声明 JavaScript 有三种声明函数的方法。 (1)function 命令 funct...
    徵羽kid阅读 420评论 0 1
  • 函数是一段可以反复调用的代码块。函数还能接受输入的参数,不同的参数会返回不同的值。 概述 函数的声明 JavaSc...
    许先生__阅读 452评论 0 1