JS 基础:变量声明
JS
变量的声明分为 创建create
、初始化initialize
和 赋值assign
。
var 声明的过程
javascript
function fn() {
var x = 1;
var y = 2;
}
fn();
- 进入
fn
,为fn
创建一个环境。 - 找到
fn
中所有用var
声明的变量,在这个环境中「创建」这些变量(即x
和y
)。 - 将这些变量「初始化」为
undefined
。 - 开始执行代码
x = 1
将x
变量「赋值」为1
y = 2
将y
变量「赋值」为2
var 例 1
js
var name = 'zky';
(function () {
if (typeof name === 'undefined') {
var name = 'xq';
console.log(1, name);
} else {
console.log(2, name);
}
})();
- 在自执行的
function
里的var
经过变量提升,先初始化name
为undefined
。 - 然后在第二步则打印
1,xq
。
function 声明过程
javascript
function fn() {}
fn2();
function fn2() {
console.log(2);
}
- 找到所有用
function
声明的变量,在环境中「创建」这些变量。 - 将这些变量「初始化」并「赋值」为
function(){ console.log(2) }
。 - 开始执行代码
fn2()
let 声明过程
javascript
{
let x = 1;
x = 2;
}
- 找到所有用
let
声明的变量,在环境中「创建」这些变量 - 开始执行代码(注意现在还没有初始化)
- 执行
x = 1
,将x
「初始化」为 1(这并不是一次赋值,如果代码是let x
,就将x
初始化为undefined
) - 执行
x = 2
,对x
进行「赋值」
例 1
javascript
let x = 'global';
{
console.log(x); // Uncaught ReferenceError: x is not defined
let x = 1;
}
console.log(x)
中的x
指的是下面的x
,而不是全局的x
- 执行
log
时x
还没「初始化」,所以不能使用(也就是所谓的暂时死区)
例 2
javascript
var liList = document.querySelectorAll('li'); // 共5个li
for (let i = 0; i < liList.length; i++) {
liList[i].onclick = function () {
console.log(i);
};
}
for( let i = 0; i< 5; i++)
这句话的圆括号之间,有一个隐藏的作用域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
- 如果
let x
的初始化过程失败了,x
变量就将永远处于created
状态。 - 无法再次对
x
进行初始化,x
永远处在暂时性死区.
当程序的控制流程在新的作用域(module function 或 block 作用域)进行实例化时,在此作用域中用 let/const 声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时性死区。
const 声明过程
const
过程跟 let
一样,但 const
只有「创建」和「初始化」,没有「赋值」过程。
总结
let、const
的「创建」过程被提升了,但是初始化没有提升。var
的「创建」和「初始化」都被提升了。function
的「创建」「初始化」和「赋值」都被提升了。