解释 JavaScript 中的作用域和作用域链


在 JavaScript 中,作用域定义了我们如何在代码的哪个部分访问变量和函数。简单来说,作用域有助于提高代码的安全性和可读性。因此,我们只能在其作用域内访问变量和函数,而不能在外部访问。

本教程将讨论多种类型的作用域。

JavaScript 中的全局作用域

全局定义的变量和函数(在所有块和函数之外)具有全局作用域。我们可以在代码的任何地方访问具有全局作用域的所有变量和函数。

语法

用户可以按照以下语法定义具有全局作用域的变量。

var global = 30;
function func() {
   var b = global; // global variable has a global scope so we can access it inside the function.
}

这里,全局变量global是在任何函数之外声明的,因此它具有全局作用域。然后,通过声明局部变量 b 并将其赋值为全局变量global的值,在函数func内部访问它。

示例

在这个例子中,我们用全局作用域定义了全局变量。我们在名为func()的函数内访问它,并从函数中返回它的值。

在输出中,我们可以观察到 func() 函数返回 20,这是全局变量的值。

<html>
   <body>
      <h2> Defining a variable with <i> global </i> scope </h2>
      <div id = "output"> </div>
      <script>
         let output = document.getElementById("output");
         var global = 20;
         function func() {
            return global;
         }
         output.innerHTML += "The value of variable named global: " + func();
      </script>
   </body>
</html>

局部/函数作用域

局部作用域也称为函数作用域。在函数内部定义的变量具有函数作用域/局部作用域。我们不能在函数外部访问这些变量。

语法

您可以按照以下语法来理解变量和函数的局部作用域:

function func() {
   var local_var = "Hi!";
}
console.log(local_var); // this will raise an error

这里local_varfunc()函数内具有函数作用域,因此我们不能在函数外部访问它。

示例

在这个例子中,我们创建了 func() 函数。在 func() 函数内部,我们定义了具有局部作用域的local_var变量,这意味着我们只能在 func() 函数内部访问它。我们可以看到,如果我们尝试在 func() 函数外部访问local_var,它会抛出一个local_var未定义的错误。要查看此错误,您需要打开控制台。

<html>
   <body>
      <h2>Defining a variable with <i> function </i> scope</h2>
      <div id = "output"> </div>
      <script>
         let output = document.getElementById("output");
         function func() {
            let local_var = 20;
            output.innerHTML += "The value of local_var inside fucntion: " + local_var + "<br/>";
         }
         func();
         // the local_var can't be accessed here
         output.innerHTML += "The value of local_var outside fucntion: " +local_var+ "<br/>";
      </script>
   </body>
<html>

块作用域

在 JavaScript 中,我们可以使用两个花括号{}来定义。块作用域表示,我们在特定块内定义的任何变量只能在该块内访问,而不能在该块外访问。用letconst关键字声明的变量具有块作用域。

语法

用户可以按照以下语法来理解变量的块作用域。

{
   let block_var = 6707;
   // block_var accessible here
}

// we can't access the block_var variable here.

在这里,我们不能在花括号外部访问block_var,因为我们是在特定块内定义它的。

注意 - 用var关键字声明的变量没有块作用域。

示例

在这个例子中,我们使用花括号定义了一个块,并定义了一个变量num。我们尝试在块内和块外访问这个变量。您可以观察到,我们不能在花括号外部访问num,因为我们是在块内定义它的。

<html>
   <body>
      <h2>Defining the variable with <i> block </i> scope </h2>
      <div id="output"></div>
      <script>
         let output = document.getElementById("output");
         {
            const num = 200;
            output.innerHTML += "Value of num inside the block: " + num + "<br>";
         }
         // num is accessible here - outside the block
         output.innerHTML += "value of num outside the block: " + num + "<br>";
      </script>
   </body>
</html>

词法作用域

词法作用域与静态作用域相同。在 JavaScript 中,当我们执行嵌套函数并尝试访问嵌套函数内的任何变量时,它首先在局部上下文内查找变量。如果它没有在嵌套函数的局部上下文中找到变量,它会尝试在从其执行函数的父上下文中查找,依此类推。最后,如果它没有在全局上下文中找到变量,则认为它是未定义的。

语法

用户可以按照以下语法来理解词法作用域。

var parent_var = 343;
var test = function () {
   console.log(parent_var);
};
test();

在上面的语法中,我们从执行函数的作用域访问了parent_var。由于函数log()不会在局部作用域中找到parent_var,它将尝试在调用函数的作用域(即全局作用域)中查找。

示例

在这个例子中,我们定义了 test() 函数和嵌套的 nested() 函数。此外,我们在 nested() 函数内部访问了 global_var 和 parent_var。由于 JavaScript 不会在局部上下文中找到这两个变量,它将首先在 nested() 函数的执行上下文中查找,然后在 test() 函数的执行上下文中查找。

<html>
   <body>
      <h2>Defining the variables with <i> lexical </i> scope</h2>
      <div id="output"></div>
      <script>
         let output = document.getElementById("output");
         var global_var = 576505;
         var test = function () {
            var parent_var = 343;
            var nested = function () {
               output.innerHTML += "The value of parent_var: " + parent_var + "<br/>";
               output.innerHTML += "The value of global_var: " + global_var + "<br/>";
            };
            nested();
         };
         test();
      </script>
   </body>
</html>

作用域链

正如作用域链这个词所暗示的那样,它是一条作用域链。例如,假设我们在函数内部定义嵌套函数。在这种情况下,它可以有自己的局部作用域,并且在嵌套函数内声明的变量不能在外部函数中访问。

因此,我们正在创建作用域链;这就是我们称之为作用域链的原因。

语法

用户可以按照以下语法学习作用域链。

function outer() {
   function inner() {
      // inner’s local scope.
      
      // we can access variables defined inside the outer() function as inner is inside the local scope of outer
   }
   
   // variables defined in the inner() function, can’t be accessible here.
}

示例

在这个例子中,inner() 函数在 outer() 函数的作用域内,这意味着我们不能在 outer() 函数外部调用 inner() 函数。inner() 函数在 outer() 函数内创建作用域链。

<html>
   <body>
      <h2>Scope Chain in JavaScript </i></h2>
      <div id="output"></div>
      <script>
         let output = document.getElementById("output");
         function outer() {
            var emp_name = "Shubham!";
            function inner() {
               var age = 22;
               output.innerHTML += ("The value of the emp_name is " + emp_name) +"<br/>";
               output.innerHTML += "The value of the age is " + age;
            }
            inner();
            
            // age can't be accessible here as it is the local scope of inner
         }
         outer();
      </script>
   </body>
</html>

在本教程中,我们讨论了 JavaScript 中的作用域和作用域链。我们讨论了全局、局部/函数、块和词法作用域。在最后一节中,我们了解了作用域链在 Javascript 中是如何工作的。

更新于:2023年1月5日

1000+ 次浏览

启动你的职业生涯

完成课程获得认证

开始
广告