今天看了tom大叔的一篇文章 还有司徒正美的文章,其中讲到一些关于javascript的小技巧的题,比较有趣,都有一些绕,不过很好理解。javascript
可是只有一道题让我琢磨半天,并非很难,可是从一开始分析方向就错了,因此记录下来分享。html
if (!("a" in window)) {
var a = 1;
}
console.log(a)
复制代码
a
输出什么?一些老的javascript选手已经作出了答案,输出是一个undefined
。但究竟为何是undefined
呢?java
最开始我思考,由于Javascript没有块级做用域,因此if
里面定义的var a = 1;
必定是会传入到window对象里面的,因此a
的输出必定是1
。固然这道题不可能这么简单,想固然的就把这几行代码输入到控制台,输出一下,发现输出的是undefined
!ruby
赤裸裸的打脸让我羞红了脸庞,怎么会这样,难道 in
操做符有什么诡异的操做吗?赶忙搜了一下in操做符,赶忙查看一下,有没有什么鲜为人知的js小技巧。函数
很快撇清了怀疑,由于并无关于操做符引起的诡异事件。既然如此,那必定是发生在window
和"a"
上面了!ui
为了清晰的查看发生了什么,我把var a
改为了var b
,发现竟然奇迹般地能够输出正确结果了。使人诧异的同时,也让我发现了看来和里面的 var a
有关,因而我定睛一看,发现并非 in
操做符的问题,而是 var
的问题spa
题目已经给出了答案,本题本质上是 var
带来的变量提高code
// var a; 已经存在
if (!("a" in window)) {
//并无进到这里
var a = 1;
} else {
//进入了这里
}
console.log(a)
复制代码
同时引出另外一个问题,最初忽略变量提高最大的缘由在于if (!("a" in window))
这句代码,自己是一个判断,a
是否存在于window
对象当中。所以,即便a === undefined
返回的也是true
。cdn
既然布尔值是true
,其实也就走不到var a = 1;
这一步了。这道题使人迷惑的缘由在于明明 if
语句没能走下去,却依然被var a = 1;
这句话带来的影响而形成问题。htm
JavaScript 中,函数及变量的声明都将被提高到函数的最顶部。
JavaScript 中,变量能够在使用后声明,也就是变量能够先使用再声明。
变量提高(Hoisting)被认为是, Javascript中执行上下文 (特别是建立和执行阶段)工做方式的一种认识。在 ECMAScript® 2015 Language Specification 以前的JavaScript文档中找不到变量提高(Hoisting)这个词。不过,须要注意的是,开始时,这个概念可能比较难理解,甚至恼人。
例如,从概念的字面意义上说,“变量提高”意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不许确。实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中。
因为if
判断语句存在 window
做用域下,所以变量提高依然生效,正由于没有块级做用域,因此存在于if
中的var
会提高到,window对象下。
如此说来本题也就解开了,一道由变量提高引起的谜题。最初却被迷魂汤迷住了双眼,正是因为对if
判断条件的信任才致使没法理解代码的走向。
这是一道很早以前的小题,咱们在平常写代码的时候通常也会格外注意做用域问题,并且大多数状况不会使用in
来判断。但假如真的须要使用,那就不得不注意变量提高致使的,in
操做符判断的不肯定性,一道小题,几分钟迷人眼,但若是是一个大型组件,一时半会还真不那么容易找到问题来源,浪费c干不说,还让代码的不肯定性提高。