美文网首页
JavaScript - 变量作用域、闭包

JavaScript - 变量作用域、闭包

作者: Hyso | 来源:发表于2019-04-08 11:06 被阅读0次

    变量作用域

    • 变量作用域就是指一个变量可以使用的范围。
    • JavaScript 中首先有一个最外层的作用域,称之为全局作用域。
    • JavaScript 中还可以通过函数创建出一个独立的作用域,其中函数可以嵌套,所以作用域也可以嵌套。

    1) 例1

    // 全局作用域
    var gender = "男";
    
    function fn() {
        // 男
        console.log(gender);
        // undefined:age 变量是在 fn 函数内部声明的,所以能访问,但是此时 age 变量还没被赋值
        console.log(age);
        // 报错:height 变量不是在 fn 函数内部声明的,所以不能访问
        console.log(height);
    
        return function() {
            var height  = 180;
        }
    
        var age = 5;
    }
    

    由上可见,JavaScript 中函数执行的时候,首先找到函数内容所有声明的的变量、函数,把他们放在作用域中,并且给变量一个初始值:undefined。接着逐条执行代码,在代码执行过程中,如果有赋值语句,则再对相应的变量赋值。

    2)例2

    function fn(callback) {
        var age = 18;
    
        callback();
    }
    
    fn(function() {
        // 报错:age is not defined
        // 查找 age 变量:
        // 1)当前作用域中没有 age 变量
        // 2)上一级作用域(全局作用域)中没有 age 变量
        console.log(age);
    })
    

    总结:查找变量作用域时,并不是看函数在哪里调用,而是看函数在哪里编写

    认识闭包

    1)例1

    function fn() {
        var a = 5;
    
        return function() {
            a++;
            console.log(a);
        }
    }
    
    // f1 指向了匿名函数
    var f1 = fn();
    // 6
    f1();
    // 7
    f1();
    // 8
    f1();
    

    分析:
    代码执行到 var f1 = fn(); 时,fn 函数执行完毕,返回匿名函数。一般情况下,函数执行完毕,变量就会释放,但是此时 JavaScript 引擎发现匿名函数要使用 a 变量,所以 a 变量并不能得到释放,而是把 a 变量放到了匿名函数可以访问的地方去了(此时的 a 变量只能被这个匿名函数可以访问到);

    2)例2

    function fn() {
        var a = 5;
    
        return function() {
            a++;
            console.log(a);
        }
    }
    
    var f1 = fn();
    // 输出 6,执行了 fn 函数,初始化了一个新的 a 变量,值为5;返回匿名函数,并把 a 变量放在了 f1 函数可以访问到的地方
    f2();
    
    var f2 = fn();
    //  输出 6,又一次执行了 fn 函数,又初始化了一个新的 a 变量,值为5;返回匿名函数,并把新的 a 变量放在了 f2 函数可以访问到的地方
    f2();
    
    var f3 = fn();
    //  输出 6,又一次执行了 fn 函数,又初始化了一个新的 a 变量,值为5;返回匿名函数,并把新的 a 变量放在了 f3 函数可以访问到的地方
    f3();
    

    3)例3

    function fn() {
        var a = {};
    
        return function() {
            return a;
        }
    }
    
    var f1 = fn();
    var f2 = fn();
    // false
    console.log(f1 == f2);
    
    var g1 = f1();
    var g2 = f1();
    var g3 = f2();
    // true
    console.log(g1 == g2);
    // false
    console.log(g1 == g3);
    

    闭包的自调用

    • 无参数
    var m = (function() {
    
    })();
    

    以上代码等于:

    function module() {
    }
    
    var m = module();
    
    • 有参数
    var m = (function(global) {
    
    })(window);
    

    以上代码等于:

    function module(global) {
    }
    
    var m = module(window);
    

    闭包的应用

    模块化开发思想:

    var k = (function KTV() {
        var leastPrice = 1000;
        var total = 0;
    
        return {
            // 购物
            buy:function(price) {
                total += price;
            }
           // 结账
            pay:function() {
                if (total<leastPrice) {
                    console.log("请继续购物");
                }
                else {
                    console.log("欢迎下次光临");
                }
            }
            // 修改最低消费金额
           editLeast:function(id, price) {
               if (id == 888) {
                   leastPrice = price;
                    console.log("现在最低消费金额为:"+ leastPrice );
               }
              else {
                    console.log("权限不足");
              }
           }
        }
    })();
    

    相关文章

      网友评论

          本文标题:JavaScript - 变量作用域、闭包

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