JS的作用域、闭包

什么是作用域
作用域是使用一套严格的规则来分辨哪些标识符对那些语法有访问权限。通俗的讲,作用域就是查找变量的地方,作用域可以分为动态作用域个静态作用域;

请看例子:

 var a=1
 function myFun(){
    var b=2
    console.log(a) //1
    console.log(b) //2
 }
 myFun() 

上面代码定义了一个变量和一个函数,函数执行的时候输出变量a的值1和变量b的值2,此时有一个全局作用域,在全局作用域内部声明了变量和函数myFun,而在函数内部就形成一个函数作用域,在这个作用域内有变量b值为2;

作用域链
结合上面的例子我们在函数内部查找a变量的时候,先在函数作用域中查找,没有找到,就去上一级的作用域去找,直到找到全局作用域,也就是在查找标识符的过程汇总有一个往外层查找的过程。好像是顺着一条链条从下往上查找,这条链条,我们就称之为作用域链。
作用域嵌套
在还没有接触到ES6的let、const之前,只有函数作用域和全局作用域,函数作用域肯定是在全局作用域里面的,而函数作用域中又可以继续嵌套函数作用域,如图:
在这里插入图片描述上图表明了作用域的嵌套关系,而在查找标识符的时候,也是从内向外查找的,这从里到外的各层作用域就组成了作用域链。

JS中的作用域类型

全局作用域
最外层的作用域

函数作用域
函数作用域是js中最常见的作用域了,函数作用域给我们最直观的体会就是,内部函数可以调用外部函数中的变量。一层层的函数,很直观的就形成了嵌套的作用域。
块级作用域
ES6 提供的let,const方法声明的标识符都会固定于块中。常被大家忽略的try/catch的catch语句也会创建一个块作用域。
词法作用域
概念
“词法作用域是作用域的一种工作模型”, 所谓的词法作用域就是在你写代码时将变量和块作用域写在哪里来决定,也就是词法作用域是静态的作用域,编译阶段就能够知道全部标识符在哪里以及是如何声明的。

闭包
什么是闭包

《JavaScript高级程序设计》这样描述:
闭包是指有权访问另一个函数作用域中的变量的函数; 《你不知道的JavaScript》这样描述: 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。

闭包使用场景

设计私有的方法和变量(封装,定义模块)。
 var counter = (function(){
        var privateCounter = 0; //私有变量
        function change(val){
            privateCounter += val;
        }
        return {
            increment:function(){  
                change(1);
            },
            decrement:function(){
                change(-1);
            },
            value:function(){
                return privateCounter;
            }
        };
    })();

设置缓存
var fn=(function(){
    var cache={}//将结果缓存到该对象中
    return function(){
        var str=JSON.stringify(arguments);
        if(cache[str]){//判断缓存中是否存在传递过来的参数,存在直接返回结果,无需计算
            return cache[str];
        }else{//进行计算并返回结果
            var sum=0;
            for(var i=0;i<arguments.length;i++){
                sum+=arguments[i];
            }
            return cache[str]=sum;
        }
    }
})()

上面的示例将计算后的结果缓存到局部变量cache当中,在调用这个函数时,先在缓存中查找,如果找不到,则进行计算,然后将结果放到缓存中并返回,如果找到了,直接返回查找到的值。

在函数外使用函数内的变量
function init(){
    var a = "1";//a是一个被init创建的局部变量
    function sayA(){//sayA是一个内部函数,闭包
        alert(a);//a
    }
    sayA();
}
init();//"a"

闭包性能

1、闭包的缺点就是常驻内存会增大内存使用量,并且使用不当很容易造成内存泄露。
2、如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。
3、可以读取函数内部的变量。
4、可以让这些局部变量保存在内存中,实现变量数据共享。

发布了49 篇原创文章 · 获赞 0 · 访问量 488

猜你喜欢

转载自blog.csdn.net/weixin_45959525/article/details/104047456