var、let、const的区别

582 阅读3分钟

面试官最想要的答案

面试时,经常会被问到var、let、const的区别,大可直接这样回答,百分百满分:

答:首先说一下var和let的区别,第一个区别是作用域不同,var是函数级作用域,let是块级作用域,比如在for循环中用var定义的变量可以在for外部访问,而用let定义的变量在for循环外部访问不到。第二个不同点是let不能在定义之前访问该变量,但var可以,只不过初始值是undefined。第三个不同点是let不可以重复定义,会报错,var可以重复定义。const和let的特点差不多,但也有一个区别,const不可以重新赋值,let可以重新赋值,但也只是在string、number、boolean这种基本类型上适用,当const定义的变量是对象时,可以对对象的键值新增或赋值,当变量是数组时,也可进行push、pop等操作。为了让变量不变也可用object.freeze(变量名),但也只能单层冻结,对里层嵌套的对象或数组失效。

答案解析

var和let的区别:

1、作用域不同:var是函数作用域,let是块作用域。在函数中声明了var,整个函数内都是有效的;而let由于是块作用域,所以如果在块作用域内定义的变量,比如说在for循环内,在其外面是不可被访问的,所以for循环推荐用let。

image.png

2、let不能在定义之前访问该变量,但是var可以。let必须先声明,再使用。而var先使用后声明也行,只不过直接使用但没有定义的时候,其值是undefined。

image.png 这是因为var和let声明的变量在变量提升时提升的是不同阶段的变量。

JS 变量的诞生有的三个阶段「创建create、初始化initialize 和赋值assign」

  • 创建:为变量a开辟内存空间
  • 初始化:a=undefined
  • 赋值:a=1

而:

  • let 的「创建」过程被提升了,但是初始化没有提升。(很多人把这种情况叫做let的暂存性死区)
  • const 的「创建」过程被提升了,但是初始化没有提升。
  • var 的「创建」和「初始化」都被提升了。

3、let不能被重新声明同一个变量,但是var是可以的

image.png

const

const和let非常像(跟var相比来说,他们之间有许多相同点),但是他们有一个主要的不同点:let可以重新赋值,但是const不能。因此const定义的变量只能有一个值,并且这个值在声明的时候就会被赋值。因此我们来看下下面的例子。

image.png 但是const是完全不可变的吗?

并不是!

如果const变量有一个数组或者对象作为其值的话,便可以像这样改变它的值。

const myConstObject = {mutableProperty: 2};

myConstObject = {};// TypeError
myConstObject.mutableProperty = 3; //ok
console.log(myConstObject.mutableProperty); // 3
const myConstArray = [1];

myConstArray = []; // TypeError
myConstArray.push(2) //ok
console.log(myConstArray); // [1, 2]

当然你不能用原始数据类型的值,比如string,number,boolean等,因为他们本质上是不可变的。

如果你想让我们的变量真正的不可变的话,可以使用Object.freeze(), 它可以让你的对象保持不可变。不幸的是,他仅仅是浅不可变,如果你对象里嵌套着对象的话,它依然是可变的。

const myConstNestedObject = {
  immutableObject: {
    mutableProperty: 1
  }
};

Object.freeze(myConstNestedObject);

myConstNestedObject.immutableObject = 10; // won't change
console.log(myConstNestedObject.immutableObject); // {mutableProperty: 1}
myConstNestedObject.immutableObject.mutableProperty = 10; // ok
console.log(myConstNestedObject.immutableObject.mutableProperty); // 10