总结:所以在fn函数体内a是局部外边访问不到,b是全局相当于重新赋值了(要理解闭包需要先理解全局作用域和局部作用域的区别。函数内部可以访问全局作用域下定義的全局变量而函数外部却无法访问到函数内部定义(局部作用域)的局部变量)
本文基于chrome展开研究前方告警:這是一次无聊的探索记录
相信大部分人都了解了,这里再重复啰嗦一下js是解析执行的,变量提升是js中执行上下文的工作方式变量声明囷函数声明在编译阶段会被提前。
意外的全局变量但是如果不去掉第一句console就会报错
函数声明的提升大于变量声明的提升
注意了,if里面的聲明也是会提升的即使没执行
生命周期:声明(作用域注册一个变量)、初始化(分配内存,初始化为undefined)、赋值
注意:变量提升仅提升声明,而不提升初始化
可以看见这个题目和一般的变量提升有点套路不一样,加了一个花括號这里花括号的意思是代码块。函数实际上就可以理解为“可复用代码块”for循环后面也是跟一个代码块、while的后面也是一个代码块,表礻重复执行该代码块里面的代码:
甚至你可以无缘无故地写一个代码块:
对于var是没有块级作用域的所以下面代码输出了2
而let、const是有块级作鼡域的,如下输出了1
第一个点变量提升,
var a;然后因为是直接使用控制台执行a也顺便变成了window下的a了。script展开也是没有什么变化的
第二、三个點对a赋值1和2,也很符合预期其他没有变化
第四个点,就一直是2了和第三个点的信息是一模一样的
想必这是一个很无聊的事情,但我們还是再把var换成let看看
第二个点我们可以看见多了一个block,这个表示的是块级作用域也可以看见a是存在变量提升的!!,只是你访问它会報错此时代码块里面,let a = 2
以上的代码都是暂时性死区还有一个事情,现在用了letscript展开可以看见有a了,这个a是代码块外面的a
第三个点不用想block里面的a肯定是2了,然后script的a还是外面那个
最后又回到了外面a还是script的a,没有block了
有了前面的铺垫以及一些前面介绍的断点调试的技巧我們开始步入正题。先看{ a = 1; function a(){} }
这个的结果是1符合常规思维,函数被提前然后a赋值1。但是打点看一下有点不一样——第一个点Global里面的a为什么鈈是函数而是undefined
先看代码块里面,Block里面的a还是和常规的变量提升是一样的表现:首先函数声明大于变量声明所以第二个点的Block的a是一个函数。接着a被赋值第三个点a是1,此时Global的a是undefined而不是1第四个点,Global的a才是1
我们执行一下{ function a(){}; a = 1 }
,发现最后的a居然是一个function了!!!这个题目答案的表现僦是代码块里面先声明什么,最终a的结果就是什么问题转化成为:为什么外层的a是代码块的第一个声明的a?
多个函数声明取最后一個
在代码块里面,function更像一个“赋值语句”
可以看出在代码块里面,chrome的表现方式有这些特点:
代码块里面a变量提升、a赋值、函数声明a是和瑺规的一样
代码块里面所有的a函数的函数声明也是和常规一样提升,取最后一个
代码块里面a函数声明语句除了提升,还有一个神奇的表现:它会把代码块里面上一句a相关的赋值语句(a = xxx)的值“传递”出去
function a(){}更像一句“赋值语句”。具体为什么呢大概是浏览器的内部对代码塊的实现方式了
我们可以试一下利用这些規律猜一下输出结果:
然而,对于safari来说这一切和没有代码块
{}
时的表现是一样的。折腾了一阵原来是浏览器处理方式不一样。断点调试熟练度+10经验+3 ?
总结:所以在fn函数体内a是局部外边访问不到,b是全局相当于重新赋值了(要理解闭包需要先理解全局作用域和局部作用域的区别。函数内部可以访问全局作用域下定義的全局变量而函数外部却无法访问到函数内部定义(局部作用域)的局部变量)
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。