总结下var、let 和 const 的区别

37次阅读

共计 1974 个字符,预计需要花费 5 分钟才能阅读完成。

前言
var 和 let 的区别是老生常谈,看到网上一些文章的总结,有的不太全面,甚至有的描述不太准确,在这里尽量全面的总结下这三者的区别。

let 是 ES6 新增的变量类型,用来代替 var 的一些缺陷,跟 var 相比主要有以下区别:
1. let 使用块级作用域
在 ES6 之前,ES5 中 js 只有全局作用域和函数作用域,例如:
if(true) {
var a = ‘name’
}
console.log(‘a’,a) // name
作用域是一个独立的地盘,让变量不外泄出去,但是上例中的变量就外泄了出去,所以此时 JS 没有块级作用域的概念。
var a = 1;
function fn() {
var a = 2;
console.log(‘fn’,a);
}
console.log(‘global’,a);
fn();
全局作用域就是最外层的作用域,如果我们写了很多行 JS 代码,变量定义都没有用函数包括,那么它们就全部都在全局作用域中。这样的坏处就是很容易冲突。ES6 中加入块级作用域之后:
if(true) {
let a = ‘name’
}
console.log(‘name’,name) // Uncaught ReferenceError: a is not defined
块作用域内用 let 声明的变量,在块外是不可见的,如果引用的话就会报错。
2. let 约束了变量提升而不是没有变量提升
在 js 中变量和函数都会提升:
function fn() {
console.log(‘a’,a);
var a = 1; // undefind
}
fn()
a 其实已经在调用前被声明了,只是没有被初始化。JavaScript 会把作用域里的所有变量和函数提到函数的顶部声明, 相当于:
function fn() {
var a;
console.log(‘a’,a);
a = 1; // undefind
}
fn()
JavaScript 会使用 undefined 缺省值创建变量 a, 事实上浏览器并没有把声明语句放到作用域的顶部,在编译阶段,控制流进入域,该域所有的变量和函数的声明先进入内存,文中代码的相对位置不会变动。
变量提升指的是变量声明的提升,不会提升变量的初始化和赋值。
并且函数的提升优先级大于变量的提升:
function fn() {
console.log(‘a’, a);
var a = 1;
function a () {
console.log(‘I am a function’);
}
}
fn() // ƒ a () {console.log(‘I am a function’);}
在上例中,let 声明的变量的作用域之外引用该变量会报错,但是否可理解为 let 没有变量提升?
let a = ‘outside’;
if(true) {
console.log(a);//Uncaught ReferenceError: a is not defined
let a = “inside”;
}
报出错误 a 没有被定义,而不是引用了全局作用域里的 a,说明 let 声明的 a 也被提升了。
原因是 let 设计中的暂时性死区:当前作用域顶部到该变量声明位置中间的部分,都是该 let 变量的死区,在死区中,禁止访问该变量。由此,我们给出结论,let 声明的变量存在变量提升,但是由于死区我们无法在声明前访问这个变量。
3. let 禁止重复声明变量
使用 var 可以重复声明变量,但是 let 不允许在同一块作用域内重复声明同一个变量:
function fn (){
var a = 1;
let a = 2;
console.log(a); //SyntaxError
}

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

function fn (a){
let a = 2;
console.log(a); //SyntaxError
}
上述代码会报语法错误;
4. let 不会成为全局对象的属性
我们在全局范围内声明一个变量时,这个变量自动成为全局对象的属性(在浏览器和 Node.js 环境下,这个全局对象分别是 window 和 global),但 let 是独立存在的变量,不会成为全局对象的属性:
var a = 1;
console.log(window.a); //1

let b = 2;
console.log(window.b); // undefined
5. const 声明的常量
以上 let 的规则同样适用于 const,但是跟 let 的区别是 const 声明的变量不能重新赋值,所以 const 声明的变量必须经过初始化。
const a = 1;

a = 2; // // Uncaught TypeError: Assignment to constant variable
const b; // Uncaught SyntaxError: Missing initializer in const declaration
最后
以上大概是总结后的内容,看来,还是多用 let、const 吧。
参考资料:http://es6.ruanyifeng.com/#do…

正文完
 0