词法作用域、块级作用域、作用域链、静态动态作用域

175 阅读2分钟

词法作用域

词法作用域就是静态作用域,词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的

块级作用域

块级作用域就是包含在{...}中的作用域。在这个作用域中,用let,const定义的变量外部无法访问,和函数作用域效果差不多

作用域链

js的主要分为全局作用域和函数作用域,作用域有上下级关系,上下级关系的确定就看函数是在哪个作用域下创建的。如:fn作用域下创建了bar函数,那么“fn作用域”就是“bar作用域”的上级。 一般情况下,变量取值到 创建 这个变量 的函数的作用域中取值。 但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。

动态作用域

词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。 让我们看一个例子来理解词法作用域和动态作用域之间的区别:

 
var value = 1;
 
function foo() {
  console.log(value);
}
 
function bar() {
  var value = 2;
  foo();
}
 
bar();
// 结果是 ???
  • 1.我们首先定义了一个value,并赋值为1;
  • 2.声明一个函数foo,函数的功能是打印 value 这个变量的值;
  • 3.声明一个函数bar,函数内部重新创建了一个变量 value 这个变量赋值为2;在函数内部执行了 foo() 这个函数;
  • 4.执行 bar() 这个函数

假设javaScript采用静态作用域,让我们分析下执行过程:

执行foo函数,首先从 foo 函数内部查找是否有变量 value ,如果没有 就根据书写的位置,查找上面一层的代码,我们发现value等于1,所以结果会打印 1。

假设javaScript采用动态作用域,让我们分析下执行过程:

执行foo函数,依然是从 foo 函数内部查找是否有局部变量 value。如果没有, 就从调用函数的作用域,也就是 bar 函数内部查找 value 变量,所以结果会打印 2。