JavaScript目前有三个关键字来声明变量,即var, let, const。 在ES6之前只有一种方法 var 来申明变量,ES6后新添了 let 和 const 声明变量。

Var (global and function scope):

  • 全局作用域,会在window上添加属性
  • 可以再次声明
  • 可以重新赋值
  • 在函数内定义时,作用域是函数内部,在函数外定义时,作用域为全局
  • 在任何变量被执行前,会对var进行变量提升(hosting),初始值为 undefined

变量提升(hosting):意味着可以在定义一个变量在未声明前

// 全局作用域

var name = "John Doe";
function logName() {
  console.log(name);
};
    
logName(); // John Doe
// Window {window: Window, self: Window, document: document, name: 'John Doe', location: Location, …}
// 在函数内定义时,作用域是函数内部

function logName() {
  var name = "John Doe";
  var id = 1;
  console.log(name);
};
    
function logId() {
  console.log(id);
}
    
logId(); // ReferenceError: id is not defined
// 在执行logId函数的时候,id没有在logId函数内定义
// 所以在全局变量中寻找id变量,也没有
// 所以是undefined
// 在函数外定义时,作用域为全局

var name = "John Doe";
if (true) {
  var name = "Daniel Joan";
}
  
console.log(name); // Daniel Joan
// 当在{}大括号中定义var时
// name的值会被重写,指向"Daniel Joan"
// 变量提升

function logName() {
  console.log(name);
  var name = "John Doe";
};
    
logName();
// undefined

let (block scope) 和 const (block scope):

  • 只有块级作用域,window无法访问
  • 不可以再次声明
  • 在变量声明之前,变量都是不可以访问的
  • 不存在变量提升(解析阶段会被创建出来,但不能被访问

二者的区别是:

需要重新分配变量的时候使用 let,例如:循环

不需要重新分配变量的时候使用 const,是constant(常数)的缩写 但是可以改变const对象的属性

let name = "John";

if(true){
    let name = "Jane";
    console.log(name); 
}

console.log(name);
// Jane
// John
// 这两个name变量是不同的变量,因为有着不同的作用域

function fn() {
  if(true){
      let name = "Jane";
      console.log(name); 
  }
  console.log(name); // let是块级作用域,name在if代码块中定义
}

fn()
// Jane
// ReferenceError: name is not defined

let 和 const是块级作用域

{
  const x = 2;
  console.log(x); // 2
}
console.log(x); // ReferenceError: x is not defined

{
  let x = 2;
  console.log(x); // 2
}
console.log(x);

let和const皆不可以再次声明

let name = "John";
let name = "Jane";
// SyntaxError: Identifier 'name' has already been declared
let name = "John";
name = "Jane";
// let可以重新赋值

const name = "John";
const name = "Jane";
// SyntaxError: Identifier 'name' has already been declared
const name = "John";
name = "Jane"; // TypeError: Assignment to constant variable.
// const重新赋值不被允许

const不可以再次赋值,可以通过改变const对象的属性进行赋值

const fullName = {
  firstName: "John",
  lastName: "Doe"
}
fullName.firstName = "Ellen"
console.log(fullName) // { firstName: 'Ellen', lastName: 'Doe' }
  • 实际开发如何选择

首先排除var在let和const之间做选择,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。

在导入库(Libraries)的时候使用const

一个是const可以提醒阅读程序的人,这个变量不应该改变;另一个是const比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;最后一个原因是 JavaScript 编译器会对const进行优化,所以多使用const,有利于提高程序的运行效率,也就是说let和const的本质区别,其实是编译器内部的处理不同.


Reference

  1. The Difference Between var, let and const in JavaScript and Best Practices
  2. educative | Difference between var, let, and const keyword in JavaScript
  3. geeksforgeeks | Difference between var, let and const keywords in JavaScript
  4. On let vs const