var、const、let区别及用法

168 阅读3分钟

在搞清楚它们之间区别之前我们首先搞清楚它们作用域的不同之处。

首先var是ES5提出声明变量的关键字,而在ES5中只有作用域分为全局作用域和函数作用域两种;const和let则是ES6新提出用于定义变量和常量的关键字,同时也新增了块级作用域这个概念。举个最通俗易懂的例子

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

如果是按照我们一贯的想法,认为应该是会输出1、2、3,然而实际上控制台输出了三次3。这和我们想的有些不一样,之所以造成这种现象的其实是var在搞鬼。

因为在循环结束后此时i的值已经变为了3,而定时器还没到时间,同时因为用var定义的i是在全局作用域内,所以定时器里的i取到的都是最后的i值,所以打印的是同样的数。

为了解决由var引起的类似问题,所以ES6中有了const和let

var和let、const的区别

  1. var声明的变量,不存在块级作用域的概念, 可以跨块级作用域访问;const和let声明的变量常量,只能在块级作用域内访问,不能跨块级作用域访问。
  2. var存在变量提升(声明的变量被提升到该作用域的最顶部),const和let不存在变量提升(也有一种说法是认为存在提升,与var不同的是只提升创建过程,初始化不提升)。
  3. var可以重复多次声明,let和const则不允许重复声明
  4. var在声明的全局变量会挂载在window对象上,可以通过window.变量名的方式访问这些变量常量;而const和let声明的变量则不会有这一行为。

var声明

如果在某个函数内使用var 声明一个变量,则这个变量就属于当前的函数作用域,如果不是在任何函数内声明的,则这个变量就属于全局作用域。

代码演示:

var a = 1; // 此处声明的a为全局变量,全局作用域内均可访问
function fn() {
  var b = 11; // 此处声明的b为局部变量,只有函数内可访问
  console.log(a); // 1
  console.log(b); // 11
}
fn()
console.log(a); // 1
console.log(b); // undefined

如果在不使用var直接声明变量的话,则该变量就会变成全局变量。

代码演示:

a = 1;
function fn() {
  console.log(a); // 1
}
fn()
console.log(a); // 1

const声明

const就是用来定义常量的,只能初始化,不能重复赋值,所以const声明常量时必须赋初始值。

以下都为错误的用法:

const a = 1;
a = 2; // 重新赋值
const a; // 未设置初始值
const a = 1;
const a = 2; // 多次声明赋值

但是const也有特殊情况,内容可以改变。

如:

const obj = {
  name: "xx",
  age: 11
}
obj.age = 22
console.log(obj.age); // 22

这是因为对象是引用数据类型,const定义的obj中保存的是对象的地址,而我们修改对象属性时并没有修改对象地址,所以const定义对象的属性的改变是允许的。

像下面这种直接改变整个对象显然就会发生错误:

const obj = {
  name: "xx",
  age: 11
}
obj = {
  name: "xx",
  age: 22
 }
console.log(obj.age); // Assignment to constant variable

let声明

let则就相当于var的升级版,改进了var的许多缺点。

如具有块级作用域:

此时将上面例子中的var改为let,则就能如我们所愿的打印 0 1 2

for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i); // 0 1 2
  }, 1000)
}

还有和const一样不能重复定义

因此最后推荐大家,除特殊情况外尽量用const和let定义常量变量,以免出现一些不必要的问题。