前言
这次的问题是自己在验证块级作用域一些相关的作用偶然发现的,虽然今后代码工作中不太可能出现这种错误,但是就怕万一呢,所以还是记录一下。
块级作用域
这是ES6中明确提出的除了全局作用域和函数作用域之外的另一个作用域。关于块级作用域具体的内容我就不详细说明了,指路阮一峰老师ECMAScript6入门,里面有很详细的块级作用域相关介绍
接下来就是重头戏,块级作用域的函数声明和变量声明
变量声明
我们首先来看变量声明
{
let a = 10;
}
console.log(a)// a is not defined
-------
{
var a = 10;
}
console.log(a)// 10
- 上面的代码,块级作用域中let声明的变量只在该作用域有效,所以会报错。而var声明的变量是会发生
变量提升到全局作用域var a = undefined,再经过a= 10赋值,因此打印出10,很清楚对吧。重头戏来了
console.log(a);//ReferenceError: a is not defined
{
a = 10;
console.log(a)//10
}
console.log(a);//10
- ???WHY?,
默认变量a = 10不是默认为var a = 10吗,应该会提升到全局作用域的顶部,但是它报错了
{
console.log(a);//ReferenceError: a is not defined
a = 10;
console.log(a)
}
console.log(a);
-
这次我在块级作用域中变量a赋值之前打印,发现也是报错,也就发现了,在
a=10之后,变量a把默认声明的变量提升到了全局作用域 -
小结
- 在块级作用域中默认声明的变量(不用var、let...),只有代码执行到声明语句之后,才可以进行访问,否则会报错。
- 在块级作用域中默认声明的变量会被提升到全局作用域(但是要在声明语句之后才能被访问到)
函数声明
console.log(a);//undefined
{
function a(){}
}
- 上面的代码很正常对吧,参照以下的块级作用域函数声明的相关规则,函数声明类似于var,会被提升到全局作用域的头部 ,因此打印undefined·
同名变量
以为就这样结束了,怎么可能,我又作死的试试了同名变量,果不其然试出问题了
console.log(a);//undefined
{
console.log(a);// function a(){}
function a() {};
a = 10;
console.log(a); // 10
};
console.log(a); //function a(){}
- ???最开始的我一脸懵逼,最后一步为什么会打印函数呢?后来我又仔仔细细的把
块级作用域、默认变量、函数声明的知识又看了一遍,知道自己错在哪里了
- 块级作用域中
函数 a类似于var变量被提升到全局作用域,var a = undefined,同时被提升到块级作用域的顶部function a(){}。 - 默认变量
a=10只有在执行之后才会能被访问到,也就是说现在不用管它 - 开始执行代码,首先打印a为undefined
- 执行块级作用域代码:打印a,由于第一步的函数声明提升,所以会打印出
function a(){};之后执行function a(){},全局作用域中的变量a赋值为一个函数;接着执行a = 10,此时需要注意,JS引擎这一步会进行LHS查询(具体见《你不知道的JavaScript上》),查找变量a,此时它在块级作用域中会找到定义好的a,并且为它赋值,此时不会发生变量提升,这时块级作用域中的a=10 - 接着执行全局作用域中的console,自然打印出
function a(){}
以为就这样结束了?我又作死的换了一下顺序,这下可好,又不一样了。。。
console.log(a);//undefined
{
console.log(a);//function a(){}
a = 10;
function a() {};
console.log(a); // 10
};
console.log(a); // 10
-
直接进入正题 前俩个console打印没有问题吧,直接开始执行a = 10,按照上一个讲解这时候是为块级作用域中的变量a赋值。因此这时候块级作用域中a = 10。接下来执行
function a(){}此时这一行代码为函数声明语句,所以执行完这一语句之后,块级作用域中的a依然是10,而全局作用域中的a也赋值为10,因此最后打印的a都为10. -
小结
块级作用域中只有执行完函数声明语句之后,才会去重写对应的全局作用域上的全局变量
总结
虽然以上的一些错误可能在日常代码中不怎么会碰到,但是我还是觉得多了解了解也是好的,这对我们理解Javascript还是有很大的帮助的,希望能通过这篇文章,能更好的理解块级作用域吧