1. var
var声明的变量只能是全局或者整个函数块的作用域
1.1 变量提升
由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量声明移动到函数或者全局代码的开头位置。
bla = 2
var bla;
因此,建议始终在作用域顶部声明变量,这可以清楚知道哪些变量是函数作用域(本地),哪些变量在作用域链上解决。重要的是,提升将影响变量声明,而不会影响其值的初始化。当到达赋值语句时,该值将确实被分配。
function do_something() {
console.log(bar); // undefined
var bar = 111;
console.log(bar); // 111
}
// is implicitly understood as:
function do_something() {
var bar;
console.log(bar); // undefined
bar = 111;
console.log(bar); // 111
}
1.2 隐式全局变量
没有被声明的变量,变为了全局变量
function b() { // 当b被调用时,
x = 3;
y = 4;
z = 5;
}
b(); // 调用b时创建了全局变量想x, y, z。
2 let const
const, let允许你声明一个作用域被限制在 块级中的变量、语句或者表达式。与 var 关键字不同的是, var声明的变量只能是全局或者整个函数块的。 var 和 let 的不同之处在于后者是在编译时才初始化(见下面)。 const声明的基本类型值不可改变
2.1 块作用域
let、const声明的变量只在其声明的块或子块中可用,这一点,与var相似。二者之间最主要的区别在于var声明的变量的作用域是整个封闭函数。
function varTest() {
var x = 1;
{
var x = 2; // 同样的变量!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
{
let x = 2; // 不同的变量
console.log(x); // 2
}
console.log(x); // 1
}
2.2 重复声明
if (x) {
let foo;
let foo; // SyntaxError thrown.
}
尤其是在switch中会遇到此错误,解决方法可在case后加上代码块
let x = 1;
switch(x) {
case 0:
let foo;
break;
case 1:
let foo; // SyntaxError for redeclaration.
break;
}
2.3 暂存死区
let const 在声明之前使用会报错,typeof也避免不了
{
typeof a;
let a = 1;
}
3 三者区别
3.1 var 和 let、const的不同点
-
var只能在function,全局中形成作用域;let、const会在代码块中形成块级作用域
-
暂时性死区
-
var可重复声明,let、const不可重复声明
-
let、const声明的全局变量不会挂在顶层对象下面
3.2 let const的区别
-
const 声明之后必须马上赋值,否则会报错
-
const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改 const 变量不能修改指针,但是可以修改值
const person = {
name: "蛙人",
age: 23
}
person.age = 18 // 没问题
person = {} // SyntaxError for redeclaration.