JS 中的 var , let , const

172 阅读2分钟

0. 标识符

就是变量、函数、属性或函数参数的名称。标识符可以由一或多个下列字符组成:

  • 第一个字符必须是一个字母、下划线(_)或美元符号($);
  • 剩下的其他字符可以是字母、下划线、美元符号或数字。

3个关键字可以声明变量:var、const和let。

其中,var 在 ECMAScript 的所有版本中都可以使用,而 const 和 let 只能在 ECMAScript 6 及更晚的版本中使用。

1. var

1.1 var 定义的变量的作用域是函数作用域

var message = "hello"
console.log(message) // "hello"

function sayHi(){
    var gretting = "hi";
    console.log(gretting);
} 

sayHi() // "hi"
console.log(gretting);   //  Uncaught ReferenceError: gretting is not defined

从上面的例子可以看到 使用 var 定义的变量具有函数作用域

假如我们在上面的函数里面定义变量的时候不使用 var ,那么我们来看看会怎么样?

function sayHi(){
    gretting = "hi";
    console.log(gretting);
} 

sayHi() // "hi"
console.log(gretting);   //  undefined
为什么会这样,因为不使用关键字,而是直接去声明的变量会成为全局对象 window 下面的属性
console.log(window.gretting) // undefined

1.2 var 声明的变量具有声明提升。

console.log(fruit) // undefined
var fruit = "apple";

为什么会输出 undefined,而不是Uncaught ReferenceError

因为 var 声明的变量具有声明提升。这段代码的真正执行顺序是:

var fruit;
console.log(fruit);
fruit = "apple";

2. let

使用 let 声明变量的方式是从 ES6 之后有的。

2.1 使用 let 声明的变量的作用域是块级作用域

if(true){
   let phone = "iPhone11";
   console.log(phone) // "iPhone"
}

console.log(phone); // ReferenceError

2.2 使用 let 定义的变量不能重复定义

let name;
let name;  // SyntaxError;标识符age已经声明过了

2.3 let 没有声明提升

console.log(age);  // ReferenceError
let age = 10;

2.4 使用 let 声明的变量不会成为 window 的属性

let a = 10
console.log(window.a) // undefined

2.5 for 循环中的 let 声明

我们先来看一段代码:

for(var i = 0;i<5;i++){
          
}
console.log(i) // 5

for(let i = 0;i<5;i++){
          
}
console.log(i) // ReferenceError

for(var i = 0;i<5;i++){
     setTimeout(()=>{console.log(i)})          
}

// 5 5 5 5 5

for(let i = 0;i<5;i++){
     setTimeout(()=>{console.log(i)})      
}

// 0 1 2 3 4

为什么会这样?

JavaScript引擎在后台会为每个迭代循环声明一个新的迭代变量。每个 setTimeout 引用的都是不同的变量实例

3.const

const 声明和 let 声明的作用差不多。具有差别的是 const 声明的时候必须赋值,并且使用 const 声明的变量不能进行修改

3.1 const 声明的时候必须赋值

const a 
const a // SyntaxError

3.2 const 声明的变量不能进行修改

const b =10
b =1 // TypeError

3.3 使用 const 声明的对象,可以修改它的属性,但是不能将其指向一个新的指针

const obj = {
    name: "tim"
}

obj.name = "jerry"

console.log(obj.name) // jerry

obj = {}

console.log(obj) // TypeError