文章转载自:汤姆大叔的博客

以前在网上搜js的一些资料的时候,逛到前端牛人博客(汤姆大叔)的时候都发现了这篇文章,发现挺有意思的,也发现自己是菜鸟,js基础不过关,后来索性转载过来自己收藏一下,正好自己也学习一下,那么大家如何呢?


题目1

if (!(“a” in window)) {

   var a = 1;

}

alert(a);

代码看起来是想说:如果window不包含属性a,就声明一个变量a,然后赋值为1。

你可能认为alert出来的结果是1,然后实际结果是“undefined”。要了解为什么,我们需要知道JavaScript里的3个概念。

首先,所有的全局变量都是window的属性,语句 var a = 1;等价于window.a = 1; 你可以用如下方式来检测全局变量是否声明:

“变量名称” in window

第二,所有的变量声明都在范围作用域的顶部,看一下相似的例子:

alert(“a” in window);

var a;

此时,尽管声明是在alert之后,alert弹出的依然是true,这是因为JavaScript引擎首先会扫墓所有的变量声明,然后将这些变量声明移动到顶部,最终的代码效果是这样的:

var a;

alert(“a” in window);

这样看起来就很容易解释为什么alert结果是true了。

第三,你需要理解该题目的意思是,变量声明被提前了,但变量赋值没有,因为这行代码包括了变量声明和变量赋值。

你可以将语句拆分为如下代码:

var a;    //声明

a = 1;    //初始化赋值

当变量声明和赋值在一起用的时候,JavaScript引擎会自动将它分为两部以便将变量声明提前,不将赋值的步骤提前是因为他有可能影响代码执行出不可预期的结果。

所以,知道了这些概念以后,重新回头看一下题目的代码,其实就等价于:

var a;

if (!(“a” in window)) {

   a = 1;

}

alert(a);

这样,题目的意思就非常清楚了:首先声明a,然后判断a是否在存在,如果不存在就赋值为1,很明显a永远在window里存在,这个赋值语句永远不会执行,所以结果是undefined。

大叔注:提前这个词语显得有点迷惑了,其实就是执行上下文的关系,因为执行上下文分2个阶段:进入执行上下文和执行代码,在进入执行上下文的时候,创建变量对象VO里已经有了:函数的所有形参、所有的函数声明、所有的变量声明

VO(global) = {

   a: undefined

}

这个时候a已经有了;


更多内容请查看:http://www.cnblogs.com/TomXu/archive/2012/02/09/2330578.html