Skip to content
On this page

关于作用域

作用域

1、全局作用域(Global Scope):定义在最外层的变量拥有全局作用域,即在整个程序中都可以访问。在浏览器环境中,全局作用域是指 window 对象。如果你在全局作用域中定义一个变量,可以在任何地方访问这个变量。

js
var globalVar = 'I am in the global scope';
function testFunction() {
  console.log(globalVar);
}
testFunction(); // 输出 'I am in the global scope'

2、函数作用域(Function Scope):在函数内部定义的变量只能在该函数内部访问,即变量的作用域被限定在该函数内部。函数作用域可以保护变量不被外部访问,防止命名冲突。

js
function testFunction() {
  var functionVar = 'I am in the function scope';
  console.log(functionVar);
}
testFunction(); // 输出 'I am in the function scope'
console.log(functionVar); // ReferenceError: functionVar is not defined

3、块级作用域(Block Scope):在 ES6 之前,JavaScript 没有块级作用域。在 ES6 中,引入了 let 和 const 关键字,用于定义块级作用域。块级作用域指的是在代码块中定义的变量只在该代码块内部有效,超出该代码块的范围就无法访问。

js
if (true) {
  let blockVar = 'I am in the block scope';
  console.log(blockVar);
}
console.log(blockVar); // ReferenceError: blockVar is not defined

4、函数参数作用域(Function Parameter Scope):在函数内部,函数参数也拥有自己的作用域。这意味着,函数参数只能在该函数内部使用,并且不会影响函数外部的变量。

js
function testFunction(parameterVar) {
  console.log(parameterVar);
}
testFunction('I am in the parameter scope'); // 输出 'I am in the parameter scope'
console.log(parameterVar); // ReferenceError: parameterVar is not defined
  • 变量的作用域及作用域

TIP

变量的作用域:JavaScript 中的作用域是层级嵌套的,当在某个作用域内访问一个变量时,JavaScript 引擎会首先在当前作用域内查找该变量,如果没有找到,则会逐层向上查找,直到找到该变量或者到达全局作用域为止。这个查找变量的过程就是作用域链的形成过程。如果在一个函数中声明了一个变量,那么在函数内部和函数外部不能同时声明一个同名的变量,否则会造成命名冲突的问题。

js
var globalVar = 'I am a global variable';
function testFunction() {
  var globalVar = 'I am a function variable';
  console.log(globalVar); // 输出 'I am a function variable'
}
testFunction();
console.log(globalVar); // 输出 'I am a global variable'

TIP

作用域链: 作用域链(Scope Chain)是指在 JavaScript 中,当执行一个函数时,查找变量的过程。当在函数内部访问一个变量时,JavaScript 引擎会首先在当前函数的作用域内查找该变量,如果没有找到,则会逐层向上查找,直到找到该变量或者到达全局作用域为止。这个查找变量的过程就是作用域链的形成过程。

  • 作用域链是由当前执行上下文的变量对象和其外部环境的引用组成的,也就是说,每个函数执行时,会创建一个新的执行上下文,其中包含该函数的变量对象。同时,执行上下文还会有一个指向外部环境的引用,这个引用指向的是定义该函数的环境,也就是函数在哪个作用域中声明的。

  • 在查找变量时,JavaScript 引擎首先在当前执行上下文的变量对象中查找该变量,如果没有找到,则会向外部环境的变量对象中查找,直到找到该变量或者到达全局作用域为止。如果还是没有找到该变量,则会抛出 ReferenceError 异常。

  • 例如,下面的代码中,当在 testFunction 函数内部访问变量 x 时,JavaScript 引擎会先在 testFunction 的变量对象中查找该变量,如果没有找到,则会向外部环境的变量对象中查找,最终找到全局变量 x。

js
var x = 'global';
function testFunction() {
  console.log(x);
}
testFunction(); // 输出 'global'

如果在函数内部声明了一个同名变量,则该变量会覆盖外部环境中的同名变量。例如:

js
var x = 'global';
function testFunction() {
  var x = 'local';
  console.log(x);
}
testFunction(); // 输出 'local'
  • 在这个例子中,当在 testFunction 函数内部访问变量 x 时,JavaScript 引擎会首先在 testFunction 的变量对象中查找该变量,找到后直接返回该变量的值,不会继续向外部环境查找。因此输出的结果是 local。
  • 作用域链的概念是理解 JavaScript 作用域和闭包等高级概念的基础,深入了解作用域链对于编写高质量的 JavaScript 代码非常重要。