ES5中作用域的理解
ES5中:
- 1.没有块级作用域
- 2.只有两种作用域:全局作用域和函数作用域
1.没有块级作用域
因为es5没有块级作用域,在es5环境中下面的花括号形同虚设
{
var foo = 123
}
console.log(foo) // 123
image.png
2.只有两种作用域:全局作用域和函数作用域
因为函数有作用域,父作用域无法访问子作用域中的变量,子作用域中可以通过作用域链访问父作用域中的变量
var flag = 789
function bar() {
//函数bar的作用域的父作用域为全局作用域
var baz = 456
console.log(flag) // 789
}
bar()
console.log(baz) // Uncaught ReferenceError: baz is not defined
image.png
ES6中块级作用域的理解
- 1.ES6:有块级作用域、全局作用域和函数作用域
- 2.ES6的代码块级作用域:对let/const/function/class声明的类型有效,对var声明的变量无效
1.ES6的代码块级作用域:对let/const/function/class声明的类型有效,对var声明的变量无效
{
let foo = 123;
}
console.log(foo); // Uncaught ReferenceError: foo is not defined
{
const bar = 456;
}
console.log(bar); // Uncaught ReferenceError: bar is not defined
{
class Person {}
}
const p = new Person(); // Uncaught ReferenceError: Person is not defined
{
var baz = 789;
}
console.log(baz); // 789 ES6的块级作用域对var声明的变量无效
image.png
{
var baz = 789;
let foo = 123;
const bar = 456;
class Person {}
}
console.log(baz); //789 ES6的块级作用域对var声明的变量无效
console.log(foo); // Uncaught ReferenceError: foo is not defined
console.log(bar); //因为上行代码报错,不会执行
const p = new Person(); //因为上行代码报错,不会执行
image.png
2 function:具有特殊性
- ES6的块级作用域对function声明的变量是有效的,
- 但是因为不同的浏览器有不同的实现:
- 大部分浏览器为了兼容以前的代码,让ES6的块级作用域对function声明的变量无效
- 在仅支持es6的环境中,ES6的块级作用域对function声明的变量是有效的
- 所以,ES6的块级作用域对function声明的变量无效,是应为浏览器的实现造成的
{
function mul(a, b) {
return a * b;
}
}
mul(2, 3); // 6
image.png
3.if/switch/for的块代码的块级作用域
3.1.if语句的代码块是有块级作用域的
const flag = true;
if (flag) {
var foo = 123;
let bar = 456;
}
console.log(foo); //123
console.log(bar); // Uncaught ReferenceError: bar is not defined
3.2.switch语句的代码块是有块级作用域的
const color = "red";
switch (color) {
case "red":
let bg = "red";
break;
default:
break;
}
console.log(bg); // Uncaught ReferenceError: bg is not defined
3.3.for循环的代码块是有块级作用域的
for (let i = 0; i < 10; i++) {
console.log("btn", i);
}
console.log(i) // Uncaught ReferenceError: i is not defined
for (var j = 0; j < 10; j++) {
console.log("btn1", j);
}
console.log(j) //10
4.块级作用域的应用场景
const btns = document.getElementsByTagName("button");
//总共有四个按钮,下面代码的实现,会使不管哪个按钮被点击,都输出第4个按钮被点击,
// 因为块级作用域对var声明的变量无效
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
console.log("第" + i + "个按钮被点击");
};
}
在es6的块级作用域出现之前,使用立即执行函数实现,因为函数有作用域.那时的作用域也只有全局作用域和函数作用域
for (var i = 0; i < btns.length; i++) {
(function (n) {
btns[n].onclick = function () {
console.log("第" + n + "个按钮被点击");
};
})(i);
}
有了es6的块级作用域后,这种问题就很容易被解决
for (let i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
console.log("第" + i + "个按钮被点击");
};
}
5.let/const的暂时性死区
- 在ES6中,使用let/const声明的变量,在声明之前,变量都是不可访问的
- 我们把这种现象称之为暂时性死区
var foo = 'abc'
if(true) {
console.log(foo) //Cannot access 'foo' before initialization
let foo = '123'
}
675cd364f2c8d6e61253c499bc8534b.png
非常感谢王红元老师的深入JavaScript高级语法让我学习到很多 JavaScript
的知识
网友评论