JavaScript的作用域与作用域链

116 阅读3分钟

作用域与作用域链

什么是作用域?

作用域是变量或函数可以访问可以看到的范围。JavaScript采用的是静态作用域。它指的是变量/函数的作用域在定义的时候就已经确定了,而不是运行时才确定。

作用域的分类:

作用域可以分为:全局作用域、函数作用域、块级作用域。

全局作用域:整个程序都可以访问到的变量或函数。在js里,使用var关键字声明的变量会被添加到全局作用域。

函数作用域:在函数内部定义的变量和函数,只能在该函数内部访问。

块级作用域:在代码块内部定义的变量和函数,只能在这个代码块里访问,代码块外部是访问不到代码块里面的东西的。

(一个代码块是由一对花括号 { } 包起来的一段代码。在js里,代码块可以创建一个块级作用域。)所以if语句的花括号{ }、循环的花括号{ }各自都是块级作用域。

示例:

// 全局作用域
var globalVariable = "全局变量";

function example() {
  // 函数作用域
  var functionVariable = "函数变量";

  if (true) {
    // 块级作用域
    let blockVariable = "块级变量";
    const constantVariable = "常量变量";

    console.log(globalVariable); // 可以访问全局变量
    console.log(functionVariable); // 可以访问函数变量
    console.log(blockVariable); // 可以访问块级变量
    console.log(constantVariable); // 可以访问常量变量
  }
}

example();
 console.log(globalVariable); // 全局变量在哪里都可以访问
 console.log(functionVariable); // 函数变量在函数外访问不到
 console.log(blockVariable); // 块级变量在代码块外面访问不到
 console.log(constantVariable); // 块级变量在代码块外面访问不到

运行结果与解释:

1.作用域.png

上述代码共出现8条console.log语句,然后前4句console.logexample()函数里面的,后4句是在example函数外的

第1句console.log  :

​	console.log(globalVariable) 因为globalVariable是全局变量,因此它在example函数内部也能执行。   

第2句console.log  :console.log(functionVariable):

​	这句consolelog语句是在if的代码块里,虽然在if这个代码块里没有定义变量functionVariable,但是if代码块的父作用域是函数作用域example,通过作用域链,子作用域i(f代码块)可以访问到父作用域(example函数)的变量functionVariable。

第34句console.log  :console.log(blockVariable); console.log(constantVariable):

​	blockVariable、constantVariable这两个变量都是在if的块级作用域里面定义的。因此可以直接访问

第5句console.log。console.log(globalVariable):

​	因为globalVariable是全局变量,所以在代码的哪个位置都可以访问。

第6句console.log。console.log(functionVariable)    

​	 functionVariable是example函数内部定义的变量,这句话已经在example函数之外了,函数里定义的变量在函数外部是访问不到的,同时在函数外并没有定义过这个变量,因此会报一个“is not defined”的错误。

第 78句console.log  

​	 这两句话里用到的变量  blockVariable和constantVariable是在代码块里定义的,同时这两句话已经在if代码块之外了,因此代码块外面并没有定义这2个变量,因此会报一个“is not defined”的错误。

作用域链

什么是作用域链?

作用域链是指,当访问一个变量时,js引擎会按照嵌套的作用域顺序查找这个变量。如果这个变量在当前作用域没有找到,就去上一级作用域找,直到找到该变量或者到达全局作用域。

示例讲解:

2.作用域链讲解.png