返回

一眼看穿JS中作用域的本质,难点全扫除

前端

作用域的定义

在javascript中,作用域是指一组变量、函数和对象可被访问的范围,它决定了这些变量、函数和对象在代码中的可见性和有效性。作用域的概念对于理解javascript代码的执行流和变量的访问权限非常重要。

作用域的分类

作用域在javascript中主要分为两种类型:全局作用域和局部作用域。

全局作用域

全局作用域是javascript代码中定义的变量、函数和对象可以被所有代码访问的范围。换句话说,在全局作用域中定义的变量、函数和对象可以在任何地方被访问。

局部作用域

局部作用域是javascript代码中定义的变量、函数和对象只能被该作用域内的代码访问的范围。换句话说,在局部作用域中定义的变量、函数和对象只能在该作用域内的代码中被访问。

变量提升

变量提升是javascript中的一个特殊行为,它将变量的声明提升到函数或块级作用域的顶部。这意味着在javascript中,变量可以在其被声明之前被使用。

function foo() {
  console.log(bar); // undefined
  var bar = 1;
}

在上面的例子中,变量bar被提升到函数foo的顶部,因此可以在其被声明之前使用。

词法作用域

词法作用域是一种作用域规则,它规定变量的有效性取决于其在代码中的位置,而不是其被调用的位置。换句话说,在词法作用域中,变量的有效性只取决于其被声明的作用域,而与函数的调用顺序无关。

function foo() {
  var bar = 1;

  function baz() {
    console.log(bar); // 1
  }

  baz();
}

在上面的例子中,变量bar在函数foo中被声明,因此它在函数foo和函数baz中都是有效的。

动态作用域

动态作用域是一种作用域规则,它规定变量的有效性取决于其被调用的位置,而不是其被声明的作用域。换句话说,在动态作用域中,变量的有效性只取决于当前执行的函数,而与变量被声明的位置无关。

function foo() {
  var bar = 1;

  function baz() {
    function qux() {
      console.log(bar); // undefined
    }

    qux();
  }

  baz();
}

在上面的例子中,变量bar在函数foo中被声明,但它不能在函数qux中被访问,因为函数qux是在函数baz中被调用的,而函数baz是在函数foo中被调用的。

闭包

闭包是javascript中的一种特殊函数,它可以访问其父函数的作用域中的变量。换句话说,闭包可以访问其父函数中定义的变量,即使这些变量在父函数返回后已经不存在了。

function foo() {
  var bar = 1;

  function baz() {
    console.log(bar); // 1
  }

  return baz;
}

var qux = foo();

qux(); // 1

在上面的例子中,函数baz是一个闭包,因为它可以访问其父函数foo的作用域中的变量bar。即使函数foo已经返回,变量bar仍然存在于内存中,因为它是闭包的一部分。

结束语

作用域是javascript中非常重要的一个概念,它对于理解javascript代码的执行流和变量的访问权限非常重要。作用域有全局作用域和局部作用域两种类型,局部作用域可以是块级作用域或函数级作用域。javascript中的变量提升行为可能会导致一些意想不到的结果,因此在使用变量时需要注意变量的提升。javascript中的词法作用域和动态作用域是两种不同的作用域规则,它们对变量的有效性有不同的影响。闭包是javascript中的一种特殊函数,它可以访问其父函数的作用域中的变量,即使这些变量在父函数返回后已经不存在了。理解javascript中的作用域对于编写正确和高效的代码非常重要。