由模块化到闭包和立即执行函数

何为闭包

闭包就是在一个函数内部创建另一个函数,让你可以在一个内层函数中访问到其外层函数的作用域。又或者说,闭包就是使一个函数能够读取其他函数内部变量。

在了解闭包之前,我们要先理解JavaScript的作用域——全局作用域和局部作用域(先不考虑块级作用域)。

直接编写在 script 标签之中的JS代码,都是全局作用域;

在函数内部就是局部作用域,这个代码的名字只在函数的内部起作用

全局作用域在页面打开时创建,页面关闭时销毁;
调用函数时创建局部作用域,函数执行完毕之后,函数作用域销毁;

  • 在全局作用域下声明的变量就是全局变量
  • 在局部作用域下声明的变量就是局部变量。
用闭包的原因

因为作用域链的存在 函数内部可以直接读取全局变量。而函数内部无法读取其他函数内部的局部变量 这也是为什么用闭包的原因。

闭包就是在一个函数内部创建另一个函数,让你可以在一个内层函数中访问到其外层函数的作用域。又或者说,闭包就是使一个函数能够读取其他函数内部变量。

关于作用域链
    <script>
        var a = 1;
        var b = 2;
 
        function fn(x) {
            var a = 10;
 
            function bar(x) {
                var a = 100;
                b = x + a;
                return b;
            }
            bar(20);
            bar(200);
        }
        fn(0);
    </script>

各个作用域的嵌套关系组成一条作用域链。

例子中 bar 函数的作用域链式 bar -> fn -> 全局, fn函数保存在作用域链式 fn -> 全局

作用域链主要是进行标识符(变量和函数)的查询,

标识符解析就是沿着作用域链一级一级的搜索标识符的过程,而作用域链就是保证对变量和函数的有序访问。
(1)如果自身作用域中声明该变量,则无需使用作用域链
在上面的例子中,如果要在 bar 函数中查询变量 a ,则直接使用 LHS 查询,赋值为 100 即可。
(2)如果自身作用域中未声明该变量,则需要使用作用域链进行查找

何时产生闭包
  • 当一个嵌套的内部(子)函数,引用了嵌套的外部(父)函数的变量(函数)时, 就产生了闭包

以下代码,可以解释闭包

    // function f1(){
    //     var m=0;
    // }
    // function f2(){
    //     var n=1;
    //     console.log(m+n);//报错 Uncaught ReferenceError: m is not defined
    // }
    // f2();

    // 如何让一个函数访问另一个函数的内部变量?
    //答案是采用闭包

    function fn1(){
        var m=6;
        function fn2(){
            var n=1;
            console.log(m+n);//输出7   可以正常访问fn1函数中的m啦;
        }
        return fn2();//return 去执行fn2函数
    }
    fn1();//输出7

闭包的特点

闭包有三个特性:
1.函数嵌套函数

2.函数内部可以引用外部的参数和变量

3.参数和变量不会被垃圾回收机制回收
使用闭包有一个优点,也是它的缺点,就是可以把局部变量驻留在内存中,可以避免使用全局变量。全局变量在每个模块都可调用,这势必将是灾难性的。

全局变量的累加

var a = 1;
function abc(){
        a++;
        alert(a);
}
abc();              //2
abc();            //3

局部变量

function abc(){
        var a = 1;
        a++;
        alert(a);
}
abc();                       //2
abc();                    //2

那么怎么才能做到变量a既是局部变量又可以累加呢?

三、局部变量的累加(闭包所能做到的)

function outer(){
        var x=10;
        return function(){             //函数嵌套函数
                x++;
                alert(x);
        }
}
var y = outer();              //外部函数赋给变量y;
y();                 //y函数调用一次,结果为11
y();   
立即执行函数

定义:函数定义之后立即执行

函数表达式方式创建:

函数表达式 声明一个匿名函数并赋值给一个变量,该变量称为函数名

var functionName=function(arg0,arg1,arg2){
//函数体
}

函数表达式后面加括号()即可立即执行函数。

var test=function(n){
    alert(n)
 }(22);  //弹出 22
匿名函数方式

匿名函数,即没有名称的函数
如果单独只写一个匿名函数,此时是不符合语法要求的 会报错。需要给 匿名函数包裹一个括号,使之成为表达式。

(function(n){
    alert(n)
 })(666); //弹出 666
 
 
 //函数体不加括号,直接执行报错,
 //Uncaught SyntaxError: Function statements require a function name
 function(n){
   alert(n)
   }(22); 

所以最简立即执行函数的形式是,小括号包裹的函数里+后面一个小括号。

let add=function(){
        function fn(x,y){
            console.log(x+y);
        }
        function sub(x,y){
            console.log(x-y);
        }
        let xmlobj={};
        xmlobj.fn=fn;
        return xmlobj;
    }();
    console.log(add.fn(1,2));//3  ,
    //这样写,只能通过add访问fn ,因为fn被暴露出去了,只能通过add去访问,就算和全局函数同名也没关系,
    //而sub没有
   //xmlobj.fn有点像export 

参考:https://blog.csdn.net/mengfanshaoxia/article/details/123052297

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值