var let const
!在 ES6 之前,JavaScript 只有两种作用域: 全局变量 与 函数内的局部变量
全局作用域
//变量在任何函数之外声明时,它就成为了一个全局变量。全局变量可以在代码的任何地方被访问或修改,包括所有函数内。
var globalVar = "I'm global";
function exampleFunction() {
console.log(globalVar); // 输出: I'm global
}
console.log(globalVar); // 输出: I'm global
exampleFunction();
函数作用域
//变量是在函数内部使用 var 关键字声明的,那么这个变量就是局部变量,它的作用范围仅限于该函数内部
function outerFunction() {
var localVar = "I'm local";
function innerFunction() {
console.log(localVar); // 输出: I'm local
}
innerFunction();
}
outerFunction();
// console.log(localVar); // 抛出错误: ReferenceError: localVar is not defined
一、var
1. 函数级作用域,有变量提升
函数级作用域例子
function txt(){
var a = 1;//局部变量
}
txt();
console.log(a)//会报错(无法在外部访问)
变量提升例子
function example() {
var a = 10;
if (true) {
var a = 20;
console.log(a); // 输出 20
}
console.log(a); // 输出 20
}
这段代码相当于
function example() {
var a; // 声明提升
a = 10; // 赋值保留在原位
if (true) {
a = 20; // 依然是修改同一个变量
console.log(a); // 20
}
console.log(a); // 20(因为一直是同一个变量)
//var在{}块级内部声明的变量在外部也是可访问的
}
为什么会有变量提升? 导致了什么问题?
1.允许函数在声明之前被调用
2.会有一些不易察觉的bug
//使用var
if (true) {
console.log(a); // undefined(变量提升)
var a = 10;
}
console.log(a); // 10
//在赋值前访问变量会得到 undefined,容易引发 bug
//使用let
if (true) {
console.log(a); // 报错:ReferenceError(暂时性死区)
let a = 10;
}
//let和const在声明前访问会抛出错误,避免了访问未定义变量的问题
二、let(ES6新增)
1. 块级作用域,不会影响外部作用域
function example() {
let a = 10;
if (true) {
let a = 20;
console.log(a); // 20
}
console.log(a); // 10(因为块作用域中的 a 是独立的)
}
2.let 关键字在不同作用域,或不同块级作用域中是可以重新声明赋值
let x = 2; // 合法
{
let x = 3; // 合法
}
{
let x = 4; // 合法
}
3. 声明时可以不用先初始化
// 在这里不可以使用 carName 变量(没有变量提升)
let carName;
4. 在相同的作用域或块级作用域中,不能使用 let/var 来重置 let/var 声明的变量
三、const(ES6新增)
1.const声明的常量必须初始化
// 错误写法
const PI;
PI = 3.14159265359;
// 正确写法
const PI = 3.14159265359;
2. 声明一个只读的常量,常量的值不能更改
const PI = 3.141592653589793;
PI = 3.14; // 报错
PI = PI + 10; // 报错
3. 使用 const 定义的对象或者数组,其实是可变的,但是我们不能对常量对象重新赋值
// 创建常量对象
const car = {type:"Fiat", model:"500", color:"white"};
// 修改属性:
car.color = "red";
// 添加属性
car.owner = "Johnson";
const car = {type:"Fiat", model:"500", color:"white"};
car = {type:"Volvo", model:"EX60", color:"red"}; // 错误
4. const 关键字在不同作用域,或不同块级作用域中是可以重新声明赋值的(在相同的作用域不行)
const x = 2; // 合法
{
const x = 3; // 合法
}
{
const x = 4; // 合法
}
四、循环作用域
1.使用 var 关键字
//声明的变量是全局的,包括循环体内与循环体外
var i = 5;
for (var i = 0; i < 10; i++) {
// 一些代码...
}
// 这里输出 i 为 10
2. 使用 let 关键字
//声明的变量作用域只在循环体内,循环体外的变量不受影响
var i = 5;
for (let i = 0; i < 10; i++) {
// 一些代码...
}
// 这里输出 i 为 5