JS深入系列之作用域
五月 18, 2021
本文共计:
679 字
预计阅读时长:
2分钟
近期做了一个比较有意义的决定,深入学习总结前端知识的每一个系列,然后形成知识树。
希望也能为正在阅读的你带来一定的温习或者提升~
作用域
什么是作用域?
作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。
—— 《你不知道的JavaScript》(上卷)p12
从引擎、编译器、作用域三个纬度认识作用域
1 | var args = 'scope'; |
引擎拿到这段代码后开始编译;
引擎借助编译器开始编译,在编译时,编译器会在当前所在的作用域内(全局作用域)声明一个
args
的变量(从未声明过);引擎开始执行代码,在当前作用域中继续寻找这个变量,如果找到了,那么就进行赋值操作;
以上用步骤拆分就是:先编译后执行;
1 | # Step 1 |
从编译运行维度来讲:
作用域分类:词法作用域 & 动态作用域
从空间范围来讲:
作用域分类:
- 全局作用域
- 函数作用域
- 块作用域
- 模块作用域(ES6 Module & CommonJS Module)
什么是词法作用域?
以下示例分析来自于:https://github.com/mqyqingfeng/Blog/issues/3
1 | var value = 1; |
假设JavaScript采用静态作用域,让我们分析下执行过程:
执行 foo 函数,先从 foo 函数内部查找是否有局部变量 value,如果没有,就根据书写的位置,查找上面一层的代码,也就是 value 等于 1,所以结果会打印 1。
假设JavaScript采用动态作用域,让我们分析下执行过程:
执行 foo 函数,依然是从 foo 函数内部查找是否有局部变量 value。如果没有,就从调用函数的作用域,也就是 bar 函数内部查找 value 变量,所以结果会打印 2。
前面我们已经说了,JavaScript采用的是静态作用域,所以这个例子的结果是 1。
我们可以欺骗词法吗?
答案:可以!
可以借助eval
&with
,可以看demo
:
1 | function foo(str) { |
这里的欺骗词法也可以理解为动态的作用域
。
1 | const obj = { a: 1, b: 2 }; |
with
可以为obj
开辟一片新的词法空间去修改,但是会有隐式声明
的诟病(泄漏变量到全局);
1 | const obj = {}; |
查看评论