一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 5 天,点击查看活动详情。
块级作用域
1. 了解块级作用域
函数作用域是作用域中最常见的,但是其他类型的作用域也是存在的,比如块级作用域。
先来看一个for循环:
for (var i=0;i < 10;i++) {
console.log(i);
}
上面这个例子在for循环的头部定义了变量i,通常是因为只想在for循环内部的上下文中使用i,而忽略了i会被绑定在外部作用域(也就是全局作用域或者函数作用域)中的事实。
再看一个例子:
var foo = true;
if (foo) {
var bar = foo * 2;
bar = something(bar);
console.log(bar);
}
bar变量只在if声明的上下文中使用,因此如果能够将它声明在if'块内部中会是一个很有意义的事情,但是,当使用var声明变量的时候,写在哪里都是一样的,因为它们最终都会属于外部作用域。
块级作用域是一个用来对之前的最小授权原则进行扩展的工具,将代码在函数中隐藏信息扩展为在块中隐藏信息。
2. let
es6 引入了let关键字,提供了除var以外的另一种变量声明方式。
let关键字可以将变量绑定到所在的任意作用域中({}),也就是说,let为其声明的变量隐式地劫持了所在的作用域。
var foo = true;
if (foo) {
let bar = foo * 2;
bar = something(bar);
console.log(bar);
}
console.log(bar) // referenceError
使用let声明的变量不会在作用域中进行提升。声明的代码在运行前,声明并不“存在”。
{
console.log(a); // referenceError
let a = 2;
}
2.1. let-垃圾回收
涉及闭包和垃圾回收机制的原理。
2.2. let-循环
for (let i=0;i < 10;i++) {
console.log(i);
}
console.log(i);// referenceError
for循环中的let不仅仅将i绑定到了for循环的块中,并且它将其重新绑定到了循环的每一次迭代中,确保使用上一次循环迭代结束时的值重新赋值。
const
es6 同时引入了const关键字,用来创建常量,如果创建完之后修改值会报错。
var foo = true;
if (foo) {
var a = 2;
const b = 7;
a = 8; // 不报错
b = 9; // 报错
}
console.log(a); // 8
console.log(b); // referenceError