美文网首页
[JavaScript基础] 作用域,立即执行函数,闭包

[JavaScript基础] 作用域,立即执行函数,闭包

作者: Darkdreams | 来源:发表于2018-11-14 18:22 被阅读0次

    作用域 scope

    作用域链精解

    [[scope]]:每个JavaScript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅提供JavaScript引擎存取,[[scope]]就是其中一个。

    [[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。

    作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链

    运行期上下文:当函数执行时,会创建一个成为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。

    function fn() {
      //代码逻辑
    }
    fn(); // 执行期上下文
    fn(); // 执行期上下文,使用完销毁
    ……
    

    查找变量:从作用域链的顶端依次向下查找。函数自身的作用域,在作用域链的顶端。

    function a() {
      function b() {
        function c() {
        } 
        c();
      }
      b();
    }
    a();
    /* 作用域链
    a 定义 a.[[scope]] ==> 0 : GO
    a 执行 a.[[scope]] ==> 0 : aAO
                           1 : GO
    b 定义 b.[[scope]] ==> 0 : aAO
                           1 : GO
    b 执行 b.[[scope]] ==> 0 : bAO
                           1 : aAO
                           2 : GO
    c 定义 c.[[scope]] ==> 0 : bAO
                           1 : aAO
                           2 : GO
    c 执行 c.[[scope]] ==> 0 : cAO
                           1 : bAO
                           2 : aAO
                           3 : GO
    */
    

    立即执行函数

    此类函数没有声明,在一次执行后即释放。适合做初始化工作,只执行一次的函数。

    只有表达式才能被执行。

    (function () {
      var a = 123;
      var b = 234;
      console.log(a + b); // 357
    }())
    //带参数
    //上面括号是形参,下面括号是实参。
    (function (a, b, c) {
      console.log(a + b + c)  // 6
    }(1, 2, 3))
    //带返回值
    var num = (function (a, b, c) {
      var d = a + b + c;
      return d;
    }(1, 2, 3))
    console.log(num);
    
    写法

    (function([形参]){}([实参])) W3C官方建议这种写法
    (function([形参]){})([实参])

    //只有表达式才能被执行符号执行
    function test() {
      console.log(123)
    }()  //error
    var test = function () {
      console.log(123)
    }()  //123
    

    在函数声明前面+ - !符号,可以把函数声明变成表达式,可让函数立即执行。但放弃了函数名字。

    ! function test() {
      console.log(123)
    }() 
    //
    // 如果再执行test(),会报错。
    // Uncaught ReferenceError: test is not defined
    

    凡是表达式都能立即执行

    function test(a, b, c, d) {
      console.log(a + b + c + d);
    }(1, 2, 3, 4)
    //不报错,但不执行。说的准确点是函数不自执行。
    //浏览器会解析为test()函数和多个表达式(1, 2, 3, 4)
    //两者没关系。
    

    闭包

    内部的函数保存到了外部,就是闭包。
    闭包将造成原有作用域链不释放,造成内存泄漏。

    // e.g 
    function a() {
      function b() {
        var bbb = 234;
        console.log(aaa);
      }
      var aaa = 123;
      return b;
    }
    var glob = 100;
    var demo = a();
    demo();
    // e.g
    function a() {
      var num = 100;
      function b() {
        num ++;
        console.log(num)
      }
      return b;
    }
    var demo = a();
    demo(); // 101
    demo(); // 102
    

    作用

    实现共有变量
    //累加
    function add() {
      var count = 0;
      function num() {
        count++;
        console.log(count);  
      }
      return num;
    }
    var addNum = add();
    addNum();  //1
    ………
    
    可以做缓存(存储结构)
    function demo() {
      var num = 100;
      function a() {
        num++;
        console.log(num);
      }
      function b() {
        num--;
        console.log(num);
      }
    return [a, b]
    }
    var demoArr = demo();
    demoArr[0](); // 101
    demoArr[1](); // 100
    
    可以实现封装,属性私有化
    模块化开发,防止污染全局变量

    相关文章

      网友评论

          本文标题:[JavaScript基础] 作用域,立即执行函数,闭包

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