⛽进阶!JavaScript核心概念篇2——词法(静态)作用域与动态作用域

656 阅读3分钟

🧑‍💻进阶!JavaScript核心概念篇2——词法(静态)作用域与动态作用域-HoiweCong

一、作用域

  • 作用域是指程序源代码定义变量的区域

  • 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限

  • JS采用词法作用域(lexical scoping)也即是静态作用域

二、静态作用域和动态作用域

  • 深入解释词法作用域原理:可以用更形象的方式解释词法作用域是如何根据函数定义的位置来确定作用域链的。比如,可以画图展示函数定义时的作用域嵌套关系,以及函数执行时如何沿着这个静态的作用域链查找变量

  • 静态作用域:优点是代码的可预测性强,变量的查找路径在代码编写时就基本确定;缺点是在某些复杂场景下,可能会导致代码不够灵活

  • 动态作用域:优点是更加灵活,能根据函数调用的上下文动态确定变量的值;缺点是代码的可维护性和可预测性较差,因为变量的查找路径在运行时才能确定

var value = 1;

function foo(){
    console.log(value);
}

function bar(){
    var value = 2;
    foo();
}

bar();//1
  • JS 采用静态作用域的执行过程

    • 执行foo函数,找foo函数内部是否有局部变量value,如果没有,查找上面一层代码,也即是value=1
  • JS 采用动态作用域的执行过程

    • 执行foo函数,找foo函数内部是否有局部变量value,如果没有,就从调用函数作用域,找bar函数内部value,也就是value=2

答案:因为JS采用的是静态作用域 ,输出1

三、动态作用域

value=1
function foo () {
    echo $value;
}
function bar () {
    local value=2;
    foo;
}
bar //2

bash 就是动态作用域,把脚本存成例如 scope.bash,然后进入相应的目录,用命令行执行 bash ./scope.bash,打印的值是2

四、思考(面试题)

//case1
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();// 不同点
}
checkscope()//local scope

//case2
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;//不同点
}
checkscope()();//local scope

答案:

两段代码输出结果都是local scope,因为JS采用的是词法作用域,函数作用域基于函数创建的位置。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效

在 case2 中,checkscope 函数返回了 f 函数,这其实形成了一个闭包。可以详细解释闭包是如何和词法作用域相互配合,使得 f 函数无论何时执行都能访问到 checkscope 函数内部的局部变量 scope

❓其他

1. 疑问与作者HowieCong声明

  • 如有疑问、出错的知识,请及时点击下方链接添加作者HowieCong的其中一种联系方式或发送邮件到下方邮箱告知作者HowieCong

  • 若想让作者更新哪些方面的技术文章或补充更多知识在这篇文章,请及时点击下方链接添加里面其中一种联系方式或发送邮件到下方邮箱告知作者HowieCong

  • 声明:作者HowieCong目前只是一个前端开发小菜鸟,写文章的初衷只是全面提高自身能力和见识;如果对此篇文章喜欢或能帮助到你,麻烦给作者HowieCong点个关注/给这篇文章点个赞/收藏这篇文章/在评论区留下你的想法吧,欢迎大家来交流!

2. 作者社交媒体/邮箱-HowieCong