Skip to content

JS 基础:变量声明

JS 变量的声明分为 创建create初始化initialize赋值assign

var 声明的过程

javascript
function fn() {
  var x = 1;
  var y = 2;
}
fn();
  1. 进入 fn,为 fn 创建一个环境。
  2. 找到 fn 中所有用 var 声明的变量,在这个环境中「创建」这些变量(即 xy)。
  3. 将这些变量「初始化」为 undefined
  4. 开始执行代码
  5. x = 1x 变量「赋值」为 1
  6. y = 2y 变量「赋值」为 2

var 例 1

js
var name = 'zky';
(function () {
  if (typeof name === 'undefined') {
    var name = 'xq';
    console.log(1, name);
  } else {
    console.log(2, name);
  }
})();
  1. 在自执行的 function 里的 var 经过变量提升,先初始化 nameundefined
  2. 然后在第二步则打印 1,xq

function 声明过程

javascript
function fn() {}
fn2();

function fn2() {
  console.log(2);
}
  1. 找到所有用 function 声明的变量,在环境中「创建」这些变量。
  2. 将这些变量「初始化」并「赋值」为 function(){ console.log(2) }
  3. 开始执行代码 fn2()

let 声明过程

javascript
{
  let x = 1;
  x = 2;
}
  1. 找到所有用 let 声明的变量,在环境中「创建」这些变量
  2. 开始执行代码(注意现在还没有初始化)
  3. 执行 x = 1,将 x 「初始化」为 1(这并不是一次赋值,如果代码是 let x,就将 x 初始化为 undefined
  4. 执行 x = 2,对 x 进行「赋值」

例 1

javascript
let x = 'global';
{
  console.log(x); // Uncaught ReferenceError: x is not defined
  let x = 1;
}
  1. console.log(x) 中的 x 指的是下面的 x,而不是全局的 x
  2. 执行 logx 还没「初始化」,所以不能使用(也就是所谓的暂时死区)

例 2

javascript
var liList = document.querySelectorAll('li'); // 共5个li
for (let i = 0; i < liList.length; i++) {
  liList[i].onclick = function () {
    console.log(i);
  };
}
  1. for( let i = 0; i< 5; i++) 这句话的圆括号之间,有一个隐藏的作用域
  2. for( let i = 0; i< 5; i++) { 循环体 } 在每次执行循环体之前,JS 引擎会把 i 在循环体的上下文中重新声明及初始化一次(即 let/const 在与 for 一起用时,会有一个 perIterationBindings 的概念)。

可理解为:

javascript
var liList = document.querySelectorAll('li'); // 共5个li
for (let i = 0; i < liList.length; i++) {
  let i = 隐藏作用域中的i;
  liList[i].onclick = function () {
    console.log(i);
  };
}

例 3

javascript
let x = x; // Uncaught ReferenceError: x is not defined
let x; //Identifier 'x' has already been declared
  1. 如果 let x 的初始化过程失败了,x 变量就将永远处于 created 状态。
  2. 无法再次对 x 进行初始化, x 永远处在暂时性死区.

当程序的控制流程在新的作用域(module function 或 block 作用域)进行实例化时,在此作用域中用 let/const 声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时性死区。

const 声明过程

const 过程跟 let 一样,但 const 只有「创建」和「初始化」,没有「赋值」过程。

总结

  1. let、const 的「创建」过程被提升了,但是初始化没有提升。
  2. var 的「创建」和「初始化」都被提升了。
  3. function 的「创建」「初始化」和「赋值」都被提升了。

git命令总结

参考链接

我用了两个月的时间才理解 let