理解JavaScript作用域和作用域链

2023-05-21 17:29:49 浏览数 (1)

​一、JavaScript中的作用域

作用域是当前的执行上下文,值和表达式在其中“可见”或可被访问。如果一个变量或表达式不在当前的作用域中,那么它是不可用的。

代码语言:javascript复制
function foo() {
	var x = 'sfa'
}
console.log(x) //  x is not defined

全局作用域和函数作用域

全局作用域:在JavaScript中 {} 外面的作用域就是全局作用域,里面的变量和函数等其他资源可以在任意地方被访问到。一般来说以下几种情况拥有全局作用域

  • 最外层函数和在最外层函数外面定义的变量
代码语言:javascript复制
// 该函数和该变量供全局使用,foo函数内部依旧能够使用foo函数(此处未演示)
var a = 23;
function foo() {
    var b = 1;
    function inner() { // 内部函数不能被全局使用
		return false
	}
}
console.log(a, foo) // 23 [Function: foo] 
console.log(b) // b is not defined
 // console.log(inner) // inner is not defined
  • 不使用var声明直接赋值的变量

因为JavaScript在执行是会自动隐式地创建该全局变量

代码语言:javascript复制
// 相当于在全局:var b;
function foo() {
    b = 1;
}
foo()
console.log(b) // 1
  • 全局对象(globalThis)

全局对象可以通过globalThis获取,浏览器环境中指 Window

代码语言:javascript复制
console.log(globalThis) // Node 环境中
Object [global] {
  global: [Circular *1],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  queueMicrotask: [Function: queueMicrotask],
  performance: Performance {
    nodeTiming: PerformanceNodeTiming {
      name: 'node',
      entryType: 'node',
      startTime: 0,
      duration: 43.25670003890991,
      nodeStart: 0.508400022983551,
      v8Start: 1.6218000054359436,
      bootstrapComplete: 33.73820000886917,
      environment: 12.502800047397614,
      loopStart: -1,
      loopExit: -1,
      idleTime: 0
    },
    timeOrigin: 1683861064321.689
  },
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  }
}

函数作用域:在函数内部定义的变量、函数和其他资源。在这个作用域内声明的变量,就只能在它这个作用域和其子作用域中才能使用。

块级作用域

ES6新增的块级作用域:用let和const声明的变量才存在块级作用域,在该代码块外部访问不到该变量。在{ }中用let和const声明的变量就是一个块级作用域。

代码语言:javascript复制
{
	let a = 1;
	console.log(a) // 1
}
console.log(a) // a is not defined 外部访问不到

二、作用域链

作用域链指的是各个作用域的嵌套关系和查找机制。

代码语言:javascript复制
function foo() {
	var b = 'foo中的b'
    function bar() {
		// 当前作用域中没有声明b则查找上一级作用域(创建该作用域的那个域),依次类推,直至到全局作用域
		return b
	}
	return bar()
}

console.log(foo()) // foo中的b

上面代码中的b就是一个自由变量,即在当前作用域中没有定义b

三、js中的执行上下文

执行上下文(简称上下文)我们可以理解成一个js代码执行的环境,在代码执行阶段被创建,里面包含了定义的所有变量、函数以及this指向等。每个上下文都有一个关联的变量对象,保存着上面说的那些数据。虽然无法通过代码访问,但是后台处理数据会用到它。

全局上下文是最外层的上下文,表示全局上下文的对象可能不一样,在浏览器中就是 window 对象;上下文在其所有代码都执行完毕后会销毁(全局上下文在应用程序退出前被销毁)。

上下文中的代码在执行的时候会创建变量对象的一个作用域链(scope chain)。

希望本篇文章能够帮助到大家!

0 人点赞