X

es6遇到混杂模式的怪异表现

2022/9/19

还是来自贴吧的题目

var a=1
{
  a=3
  function a(){}
  a=4
  function a(){}
  a=5 
}
console.log(a)

求结果?

第一眼我觉得是1

毕竟function a会提升 形成遮蔽

块级作用域内的a都会等同let 修饰

然后我跑了下 node下报错

也确实 严格模式下不能这样写

于是去浏览器跑了下

结果输出4

???喵喵喵???

这不科学的感觉油然而生

于是断点跟踪:

0.png

提升~

1.png

2.png

这里已经赋值到全局了

3.png

4.png

5.png

但是 a=5没有到全局

6.png

加一行看看

7.png

确实 之后就是表现出let的修饰行为

8.png

总结下 :

从现象来看 大概结论就是 松散模式下 支持let的环境,

function 提升区域内没有修饰的同名变量会被视为var修饰

之后的会被视为let。

但这一行为我没找到具体规范说明做支撑,不确定其它浏览器环境表现是否一致。

ps:如果你试过严格模式 只用一个function a就会看到块级内a是被当作let修饰 外部不影响

去掉严格模式就会发现function a前的都会引用到全局,也就是被当作var对待了

来更多栗子 / chrome

{
 function a(){}
}
console.log(a)

输出function a

{
 function a(){}
 a=2
}
console.log(a)

输出function a

{
 a=2 
 function a(){}
}
console.log(a)

输出2

是不是 很神奇~

var a=2
{
  function a(){}
}
console.log(a)

这里输出 function a

可以看出 function提升是穿透了块级

但它是在执行到块级的时候才提升的

mozilla的文档也有强调 松散模式下 应该避免在块级申明方法

它给的例子里 在方法提升过程中 不同内核浏览器执行赋值的位置不一致

Commit