IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    再探javascript作用域

    三水清 (ksky521@gmail.com)发表于 2015-11-28 03:29:12
    love 0

    对于javascript作用域的理解,之前整理过两篇文章:《javascript作用域和作用域链》《javascript的词法作用域》。最近读了周爱民老师的《javascript语言精髓》,对javascript作用域有了新的认识,特地整理下思路。

    javascript的作用域广义来分:语法作用域和变量作用域。

    javascript语法作用域

    javascript语法作用域是讨论代码的组织结构上抽象,可以理解为讨论的是“圈地”问题,也有书籍中对纯粹的语法作用域称为“静态作用域”。

    语法作用域分四级,下标依次增高

    级别 作用域
    级别一 表达式
    级别二 语句/批语句
    级别三 函数
    级别四 全局(宿主)
    1. 同级别可以平行也可以相互嵌套(包含)
    2. 高级别可以嵌套(包含)低级别
    3. 低级别不可以嵌套(包含)高级别作用域;假如低级别嵌套高u别,可以理解成相互平行,例如下面的代码是完全等效的
    if(true){
        //
        function fn(){
            //
        }
    }
    
    if(true){
        //
    }
    function fn(){
        //
    }
    

    批语句作用域

    批语句作用域的“{}”是用来声明被影响的代码,如果单纯理解为复合语句的“{}”则会报错,例如下面的代码:

    try
        var a = 2;
    catch(e);
    

    批语句作用域包括:try{}catch(e){}finally{}和switch

    for( var i = 0; i < 10; i++){ } console.log(i);//10
    

    spidermonkey 1.7 添加了let关键字,所以:

    for( let i = 0; i < 10; i++){ } console.log(i);//报错,undefined
    

    javascript变量作用域

    变量的可见性 和 生存周期;即大家常说(或者常被理解)的作用域。

    变量作用域完成对信息的隐蔽,也就是处理“割据”的问题,也有书籍中对执行期的变量作用域为“动态作用域”。

    变量作用域没有语句级别,分为:表达式、函数和全局三个级别。

    表达式

    表达式级别作用域,变量创建出来被立即使用。

    表达式级别作用域,都是匿名的。

    var date = 'date:'+new Date;
    var foo = (100 + function(){
        return 100
    });
    

    函数

    局部变量,对内可见;对外不可见

    全局

    在全局范围内任意声明变量。

    在函数内部不使用var 声明而直接赋值的变量,该变量会被隐式的在全局中声明

    全局变量可以理解为Global对象中的成员,也可以被解释为宿主对象,在浏览器中就是window对象

    显性声明和隐性声明 虽然都是全局变量,但是而这处理规则却不同

    var a = 100;
    delete a; //因为dontDelete为false,所以返回false
    a = 100;
    delete a; //因为dontDelete 为true,所以返回true
    

    总结下javascript的作用域

    1. javascript没有块级作用域
    2. 语法作用域不等于变量作用域
    3. 变量的可见性受限于它所在的语法结构的(语法)作用域
    • 补充:如果语言没有实现相应的变量作用域,那么该变量的可见性会溢出到同级的其他结构中,例如 if、for块级语句
    • 特例:spidermonkey javascript 1.7 let 关键字会实现语句级别的变量作用域

    变量声明次序问题

    javascript不同于C和java语言,javascript是解释执行的语言。语法解析会在执行之前,语法解析会建立一个类似“变量表”的对象,并且赋值为undefined。

    if ( !a ){
        alert(a); //undefined
        var a = 1;
    }
    alert(a); //1
    

    变量作用域和变量的生存周期

    变量作用域讨论的是解决变量在哪个范围内存储;生存周期讨论的是代码执行中什么时候创建和释放一个变量。

    创建:

    1. js引擎做语法分析,发现显性的声明
    2. js引擎代码执行时,发现隐性的未被创建的变量时

    释放:

    1. js引擎执行到函数结束/退出时,将清除的函数的未被引用的变量
    2. js引擎执行到全局代码结束,或者引擎卸载和重新载入时,将清除全局的变量和数据引用

    所以生存周期包括:函数内局部执行期间,函数外全局执行期间。变量的生存周期创建和释放过程就是内存的占用和释放过程



沪ICP备19023445号-2号
友情链接