一、作用域问题
var是函数作用域,一旦声明,在全局范围内都有效。
let是块级作用域,代码块内声明的变量在代码块之外调用会报错
{ let a = 10; var b = 1;}console.log(a); //报错console.log(b) //1
for循环的计数器,适合使用let命令;且for循环有一个特殊之处,即设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
二、是否存在变量提升
var存在“变量提升”,变量可以在声明之前使用,值为undefined;
let不存在变量提升,它所声明的变量一定要在声明之后使用,否则报错。
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
三、可否被重复声明
var允许在相同作用域内,重复声明同一个变量;
let不允许在相同作用域内,重复声明同一个变量。
// 报错 Identifier 'a' has already been declared
function func() {
let a = 10;
var a = 1;
}
// 报错 Identifier 'a' has already been declared
function func() {
let a = 10;
let a = 1;
}
function func() {
var a = 10;
var a = 1; //a:1
}
四、暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”这个区域,不再受外部影响。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
// 在let命令声明变量之前,都属于变量的“死区”
五、其它
const命令
const声明一个只读的变量,一旦声明,常量的值就不能改变。复杂类型指针指向的地址不能更改,内部数据可以更改。
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
const一旦声明变量,就必须立即初始化,不能等到以后再赋值。
const foo;
// SyntaxError: Missing initializer in const declaration
顶层对象的属性
顶层对象:浏览器环境(window对象),Node(global对象)
顶层对象的属性赋值与全局变量的赋值是同一件事。
var、function命令声明的全局变量,依旧是顶层对象的属性;
let、const、class声明的变量,不属于顶层对象的属性
var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1
let b = 1;
window.b // undefined