ES6 一共有 6 种声明变量的方法。
var和function(声明的全局变量,是顶层对象的属性(window)) let和const和class (声明的全局变量,不属于顶层对象的属性) import
区别分为以下几个方面:
1.块级作用域
2.不存在变量提升
3.暂时性死区
4.不可重复声明
5.let const 声明的全局变量不会挂在顶层对象上
一.什么是块级作用域?为什么需要块级作用域?用在var let/const的区别?
1.只要被包裹在在{}中都是一个块级作用域。例如:if、for、function、或者是直接只写一个{}。
function method(){
let n = 5;
{
let n = 10;
console.log(n); // 10 内层的n
}
console.log(n); // 5 当前层的n
}
2.在es5里只有全局作用域和函数作用域,这样会有很多麻烦的事情。
(1)内层变量可能覆盖外层变量 ( 函数,变量声明被解释器"提升"到方法体的最顶部,初始化不会提升)
var a = 2; // 声明a 并初始化为2
function method(){ //
console.log(a); //undefined
var a = 3; //作用域为整个函数
}
method();
(2)用来计数的循环变量泄露为全局变量
var s = 'hello';
for (var i = 0; i < s.length; i++) { // 此处的i是全局变量
console.log(s[i]); // i为此次for循环使用的变量
}
console.log(i); // 5 全局范围都可以读
二.不存在变量提升
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
三.暂时性死区
定义:该区域只要存在let,const,进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
var tmp = '123'
if (true) { //进入这个区域,tmp已经存在了,只是不可获取
tmp = 'abc'; // ReferenceError
let tmp;
}
暂时性死区和不能变量提升的意义:为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。
四.不可重复声明
let,const不允许在相同作用域内,重复声明或者定义同一个变量。
// 报错
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
不能在函数内部重新声明参数。
function func(arg) {
let arg;
}
func() // 报错
五.let const 声明的全局变量不会挂在顶层对象上
var a = 1;
window.a // 1
let b = 1;
window.b // undefined
此处是let var在块级作用域和函数中的声明
es5中,函数只能在顶层作用域和函数内部声明,不能再块级作用域声明。但是浏览器不遵守这个规定。
if {
function f() {} // 对于es5应该报错,但是浏览器是正常运行的
}
es6中,允许在块级作用域声明函数,声明函数的行为等同于let
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
}
f();
}());
在es5中,内部函数提升,则先打印'I am inside!
在es6中,没有提升,则先打印'I am outside!',但是上段代码在支持es6的浏览器中报错,因为浏览器的实现可以不遵守上面的规定,有自己的方式。
方式为:
允许在块级作用域内声明函数。
函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
同时,函数声明还会提升到所在的块级作用域的头部。
剖析const
保证的并不是变量的值不得改动,保存的只是一个指向实际数据的指针,保证这个指针是固定的(即总是指向另一个固定的地址)
const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
// 将 foo 指向另一个对象,就会报错,因为不能指向另一个地址
foo = {}; // TypeError: "foo" is read-only
let、const使用场景:
-
let使用场景:变量,用以替代var。
-
const使用场景:常量、声明匿名函数、箭头函数的时候。