一、var
如果使用关键字 var 声明一个变量,那么这个变量就属于当前的函数作用域,如果声明是发生在任何函数外的顶层声明,那么这个变量就属于全局作用域。举例说明:
var a = 1; //此处声明的变量a为全局变量
function foo() {
var a = 2;//此处声明的变量a为函数foo的局部变量
console.log(a);//2
}
foo();
console.log(a);//1
如果在声明变量时,省略 var 的话,该变量就会变成全局变量,如全局作用域中存在该变量,就会更新其值。如:
var a = 1; //此处声明的变量a为全局变量
function foo() {
a = 2;//此处的变量a也是全局变量
console.log(a);//2
}
foo();
console.log(a);//2
注意:var 声明的变量存在提升(hoisting)。
二、提升
提升是指无论 var 出现在一个作用域的哪个位置,这个声明都属于当前的整个作用域,在其中到处都可以访问到。注意只有变量声明才会提升,对变量赋值并不会提升。如下例所示:
console.log(a);//undefined
var a = 1;
该代码段跟下列代码段是一样的逻辑:
var a;
console.log(a);//undefined
a = 1;
而如果对未声明过的变量进行操作,就会报错
console.log(b);//假设b未声明过,Uncaught ReferenceError: b is not defined
三、let
let 声明的变量,具有如下几个特点:
如下面几个例子所示
let a = 1;
console.log(a);//1
console.log(b);//Uncaught ReferenceError: b is not defined
let b = 2;
function foo() {
let a = 1;
let a = 2;//Uncaught SyntaxError: Identifier 'a' has already been declared
}
以下是一个经典的关于 var 和 let 的一个例子:
for (var i = 0; i < 10; i++) {
setTimeout(function () {
console.log(i);
}, 100)
};
该代码运行后,会在控制台打印出10个10.若修改为:
for (let i = 0; i < 10; i++) {
setTimeout(function () {
console.log(i);
}, 100)
};
则该代码运行后,就会在控制台打印出0-9.
四、const
const 声明方式,除了具有 let 的上述特点外,其还具备一个特点,即 const 定义的变量,一旦定义后,就不能修改,即 const 声明的为常量。
例如:
const a = 1;
console.log(a);//1
a = 2;
console.log(a);//Uncaught TypeError: Assignment to constant variable.
但是,并不是说 const 声明的变量其内部内容不可变,如:
const obj = { a: 1, b: 2 };
console.log(obj.a);//1
obj.a = 3;
console.log(obj.a);//3
所以准确的说,是 const 声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。
五、总结
var声明的变量会挂载在window上,而let和const声明的变量不会
var a = 100;
console.log(a, window.a); // 100 100
let b = 10;
console.log(b, window.b); // 10 undefined
const c = 1;
console.log(c, window.c); // 1 undefined
var声明变量存在变量提升,let和const不存在变量提升
console.log(a); // undefined a已声明还没赋值,默认得到undefined值
var a = 100;
console.log(b); // 报错:Cannot access 'b' before initialization
let b = 10;
console.log(c); // 报错:Cannot access 'c' before initialization
const c = 1;
let和const声明形成块作用域
if (1) {
var a = 100;
let b = 10;
}
console.log(a); // 100
console.log(b) // 报错:b is not defined
if (1) {
var a = 100;
const c = 1;
}
console.log(a); // 100
console.log(c) // 报错:c is not defined
同一作用域下let和const不能声明同名变量,而var可以
var a = 100;
console.log(a); // 100
var a = 10;
console.log(a); // 10
let a = 100;
let a = 10;
//报错: Identifier 'a' has already been declared
暂存死区
var a = 100;
if (1) {
a = 10;
let a = 1;
}
//报错:Cannot access 'a' before initialization
const
1、一旦声明必须赋值,不能使用null占位。
2、声明后不能再修改。
3、如果声明的是复合类型数据,可以修改其属性。
const a = 100;
const list = [];
list[0] = 10;
console.log(list);//[10]
const obj = { a: 100 };
obj.name = 'apple';
obj.a = 10000;
console.log(obj);//{a: 10000, name: "apple"}