JavaScript - 词法作用域
什么是词法作用域?
词法作用域指的是表达式的定义区域。换句话说,某项的词法作用域就是它被生成时的上下文。
词法作用域有时也被称为静态作用域。某项的词法作用域并不总是由其被调用(或执行)的位置决定。对象的词法作用域就是其定义空间。
因此你可能知道,变量和方法具有不同级别的作用域 −
全局作用域: 在任何函数或块外部定义的变量,但可在整个程序中访问。
局部作用域: 在函数或块内部定义且只能在该函数或块内访问的变量被视为局部作用域。
嵌套作用域: 内部函数可以访问其父函数中的变量。
块作用域: 使用 let 和 const 定义的变量仅在其声明的块中有效,例如循环或条件语句。
现在让我们在下面的部分中查看一些 JavaScript 中词法作用域的示例。
示例 1
让我们看下面的示例代码 −
// 在全局作用域中定义一个变量
const myName = "Shwetaa";
// 从函数中调用 myName 变量
function getName() {
return myName;
}
在上面的示例代码中,我们在全局作用域中定义了 myName 变量,并在 getName() 函数中使用了它。
因此这里的问题是,myName 的词法作用域是由哪个空间覆盖的?是全局作用域还是 getName() 函数的局部作用域?
因此你要记住,词法作用域指的是定义空间,而不是调用空间。由于我们在全局环境中定义了 myName,其词法作用域是全局的。
示例 2
让我们看另一个 JavaScript 中词法作用域的示例 −
function getName() {
const myName = "Swati";
return myName;
}
因此这里的问题是,myName 的词法作用域在哪里?
答案是,注意我们如何在 getName() 内定义并调用了 myName。因此,myName 的词法作用域是 getName() 的局部环境,即 myName 的定义空间。
词法作用域是如何工作的?
能够访问 JavaScript 表达式的代码是由其定义的环境决定的。
换句话说,只有在某项词法作用域内的代码才能访问它。例如,查看下面的代码 −
// 定义一个函数
function myLastName() {
const lastName = "Sharma";
return lastName;
}
// 定义另一个函数
function showFullName() {
const fullName = "Swati " + lastName;
return fullName;
}
// 调用 showFullName():
console.log(showFullName());
输出
上面的调用将返回 −
Uncaught ReferenceError: lastName is not defined
注意,前面的代码片段调用 showFullName() 时产生了 Uncaught ReferenceError 错误。该错误是因为该项只能被其词法作用域内的代码访问。
因此,showFullName() 函数及其内部代码无法访问 lastName 变量,因为它是在不同的作用域中定义的。换句话说,lastName 的词法作用域与 showFullName() 不同。
lastName 的定义空间是 myLastName(),而 showFullName() 的词法作用域是全局环境。
现在,查看下面的代码 −
function showLastName() {
const lastName = "Sharma";
return lastName;
}
// 定义另一个函数:
function displayFullName() {
const fullName = "Swati " + showLastName();
return fullName;
}
// 调用 displayFullName():
console.log(displayFullName());
displayFullName;
这将生成下面的结果 −
Swati Sharma
因为 showLastName() 和 displayFullName() 在同一个词法作用域中,上面的示例中它们都返回了 "Swati Sharma"。
换句话说,因为这两个函数编写在同一个全局作用域中,displayFullName() 可以调用 showLastName()。
Summary
理解 JavaScript 中的词法作用域对于创建干净、可维护的代码非常重要。通过正确地为变量和函数设置作用域,你可以最小化命名冲突,提高代码可读性,并防止不良影响。理解词法作用域将带来更有序和高效的程序。