var、let和const 的区别和实现原理
es6里面新增了两个声明变量的方法,一个是let,用于声明变量。一个是const,用于声明常量。var、let和const的区别经常会被面试官问到,大多数人都可能回答的是作用域和变量提升这两方面的不同,但你们知道内在原理吗?
下面我们就从声明过程
、内存分配
和变量提升
三个方面来看一下这三者之间的区别。
声明过程
var
遇到有var的作用域,在任何语句执行前都已经完成了声明和初始化
,也就是变量提升而且拿到undefined的原因由来。
通过下面示例可以看到变量a的声明跑到console.log的前面去了,只是赋值还是在console.log之后进行赋值的,console.log得到的结果就是undefined. 这就是所谓的变量提升了。
console.log(a); // undefined |
let
解析器进入一个块级作用域
,发现let关键字,变量只是先完成声明
,并没有到初始化那一步。此时如果在此作用域提前访问,则报错xx is not defined,这就是暂时性死区
的由来。等到解析到有let那一行的时候,才会进入初始化阶段。如果let的那一行是赋值操作,则初始化和赋值同时进行。
let初始化赋值之前访问,就会报错未定义变量
console.log(b); // b is not defined |
const
const、class都是同let—样的道理。const声明的是一个常量,常量是不可修改
的,在没有完成初始化和赋值操作是访问会报错,不能重复声明
同一个常量。
内存分配
var
var的话,会直接在栈内存里预分配内存空间,然后等到实际语句执行的时候,再存储对应的变量,如果传的是引用类型,那么会在堆内存里开辟一个内存空间存储实际内容,栈内存会存储一个指向堆内存的指针
let
let的话,是不会在栈内存里预分配内存空间,而且在栈内存分配变量时,做一个检查,如果已经有相同变量名存在就会报错 Identifier ‘变量’ has already been declared
如果用let重复声明同一个变量,那么这时候就会报错:变量b已经被声明了
let b = 10; |
const
const的话,也不会预分配内存空间,在栈内存分配变量时也会做同样的检查。不过const存储的变量是不可修改
的,对于基本类型来说你无法修改定义的值,对于引用类型来说你无法修改栈内存里分配的指针,但是你可以修改指针指向的对象里面的属性
const声明的常量是不可以直接更改的,一旦你尝试着去修改一个常量的时候,浏览器就会告诉你,常量不可以被修改!
const c = 3.1415926; |
变量提升
let const和var三者其实会存在变量提升
let只是创建过程提升,初始化过程并没有提升,所以会产生暂时性死区。
var的创建和初始化过程都提升了,所以在赋值前访问会得到undefined
function的创建、初始化、赋值都被提升了
function:声明、初始化、赋值一开始就全部完成,所以函数的变量提升优先级更高。