书写在块语句中的代码是如何预解析的?
我们都知道 JS 中,在 ES6 之前 作用域分为全局作用域和函数作用域,函数作用域也是块作用域的一种,虽然这种情况我们平时很少用到,官方API 文档也没有说明,但是在实际的过程当中能够发现以下规律:
这里所讲的块作用域的情况是指{ }单独应用的时候
当在块语句内引用的时候
1.将函数写在块语句中,命名函数只会预解析,不会预赋值,只有在执行块语句的时候,赋值函数
2.如果块语句中出现变量和函数名相同的情况时,执行块语句,最后打印的是正常顺序赋值的结果
3.使用ES6语法 let 和 const 的时候遵从 ES6 对应规则的变量访问机制,定义机制,赋值机制
当在块语句外引用的时候
1.得到的变量是最后一个重名函数上面的赋值变量结果,如果上面没有重名的赋值变量,那么得到的就是这个函数
如果语句块中变量和函数名相同时,只有一个变量和一个函数,函数在变量前,最后打印函数
如果语句块中的变量是函数,且有重名变量在函数前时,打印的就是这个变量
2.在块语句中,不管有几个同名函数,都会被最后一个覆盖掉
console.log(a) // undefined
let a = 10
console.log(a) // 10
{
console.log(a) // 函数a
a = 2
console.log(a) // 2
function a(){ }
console.log(a) // 2
a = 5
console.log(a) //5
}
console.log(a) // 2
let a = 10
{
console.log(a) // 执行到这里的时候,函数内的函数名开始对应的赋值,重名的时候,后面的会覆盖掉前面的,这里打印的是 内容是 s=3 的函数,块语句中的代码接下来就是按照顺序赋值
function a(){ var s = 1}
a = 5
console.log(a) //5
function a(){ var s = 2}
a = 9
console.log(a) //9
function a(){ var s = 3}
a = 100
console.log(a) //100
}
console.log(a) // 这里我们得到的是块语句中,最后一个重名的函数名前面的重名变量,如果前面没有重名变量,那么得到的就是最后一个函数, 和函数后面的重名变量没有关系.