变量与作用域

变量是存储数据的地方。声明一个变量,相当于申请了一块内存地址,变量赋值就是将数据存储于这块内存之中。

变量

我们使用 var 关键词来声明变量:

var name = 'ruims';

从编译原理的角度理解变量声明

先看一个简单的声明语句:

var name = 'xiuyan';

在 JS 引擎眼里,它却包含了两个声明:

var name; //(编译时处理)
name = 'xiuyan'; //(运行时处理)

此处的编译时处理和运行时处理,分别对应编译阶段和执行阶段,下面详细解释:

编译阶段

主角:编译器登场!

  • 查看当前作用域是否有 name变量
  • 如果有,忽略当前变量声明
  • 如果没有,在当前作用域里新增一个 name

执行阶段

主角:JS引擎登场!

  • 查看当前作用域是否有 name变量
  • 如果有,进行赋值
  • 如果没有,递归查找父作用域
  • 如果全局也没有,就在全局作用域创建该变量

这就是变量声明的逻辑。

作用域

作用域存储和访问变量的一套规则,一个区域。

变量声明是在一个作用域内,变量访问也是在一个作用域内。

作用域分为这几种:

1. 全局作用域

全局变量:声明在任何函数之外的顶层作用域的变量。全局变量拥有全局作用域

2. 函数作用域

在函数内部定义的变量,拥有函数作用域

function sayHello() {
// hello 被定义成局部作用域变量
var hello = 'hello everyone';
console.log(hello);
}
console.log(hello); // 抛出错误:hello 在全局作用域未定义

3. 块级作用域

  • 必须用块写法
  • 必须是let或者const声明
{
let a = 1;
console(a);
}

4. 模块作用域

模块作用域是 CommonJS 中的作用域规则。在 nodejs 中,任何独立的脚本文件中声明的变量都相互独立,互不污染