JS作用域

LHS 和 RHS 查询

LHS (Left-hand Side) 和 RHS (Right-hand Side) ,是在代码执行阶段 JS 引擎操作变量的两种方式,二者区别就是对变量的查询目的是 变量赋值 还是 查询 

LHS 可以理解为变量在赋值操作符(=)的左侧,例如 a = 1,当前引擎对变量 a 查找的目的是变量赋值

RHS 可以理解为变量在赋值操作符(=)的右侧,例如:console.log(a),其中引擎对变量a的查找目的就是 查询

什么是作用域

作用域 指程序中定义变量的区域,它决定了当前执行代码对变量的访问权限。

javascript 中大部分情况下,只有两种作用域类型:

  • 全局作用域:全局作用域为程序的最外层作用域,一直存在。
  • 函数作用域:函数作用域只有函数被定义时才会创建,包含在父级函数作用域 / 全局作用域内。

由于作用域的限制,每段独立的执行代码块只能访问自己作用域和外层作用域中的变量无法访问到内层作用域的变量。

作用域链

[success]当可执行代码内部访问变量时,会先查找本地作用域,如果找到目标变量即返回,否则会去父级作用域继续查找...一直找到全局作用域。我们把这种作用域的嵌套机制,称为 作用域链。[/success]

用图片表示,上述代码一共有三层作用域嵌套,分别是:

全局作用域

foo 作用域

bar 作用域

词法作用域

词法作用域Lexical Scopes)是 javascript 中使用的作用域类型,词法作用域 也可以被叫做 静态作用域

 var value = 1;

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

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

bar();

// 结果是 1

词法作用域,就意味着函数被定义的时候,它的作用域就已经确定了,和拿到哪里执行没有关系,因此词法作用域也被称为 “静态作用域”

块级作用域

ES6 标准提出了使用 let 和 const 代替 var 关键字,来“创建块级作用域”。

总结

1.javascript 语言层面只原生支持两种作用域类型:全局作用域 和 函数作用域 。全局作用域程序运行就有,函数作用域只有定义函数的时候才有,它们之间是包含的关系。

2.作用域之间是可以嵌套的,我们把这种嵌套关系称为 作用域链

3.作用域中查询变量时,只能查询 本地作用域 及 上层作用域,不能查找内部的函数作用域。

4.javascript 中使用的是 “词法作用域”,函数作用域的范围在函数定义时就已经被确定,和函数在哪执行没有关系。

5.闭包的本质是利用了作用域的机制,来达到外部作用域访问内部作用域的目的。

参考:

你不懂 JS —— 作用域与闭包

从 LHS 与 RHS 角度浅谈Js变量声明与赋值

JS闭包与作用域

阅读剩余
THE END