看下面的代码:
if (!("aa" in window)) {
alert('oh my god');
var aa = 1;
}
alert("aa" in window);
alert(aa);
回答以下问题:
会报错吗?会弹出几次?
第2个alert是true还是false?
第3个alert弹出什么?
为什么?
思考下,然后测试下,如果你回答正确,那么后面的文章就不用看了。
-----------------------------
在JS里定义变量太简单了,直接一个var ,甚至不用var都可以:
var a = 1;
这里a就是变量名,1就是变量值。唉,这个太基础了。看下面的代码:
var a;
alert(a);
以firebug测试,会弹出undefined,这个是大家很熟悉的一个字符串了,貌似表示变量未定义。但我觉得,我已经var了啊,这就是定义了嘛,只是没有附值而已。
我们来个真正的没有定义的:
alert(a);
没错,就是直接alert一个根本没有出现过的变量,这会如何?
firebug直接报错了:a is not defined.意思是a没有定义。这个结合前面的代码来看,让人困惑。这个没有定义和前面的未定义有什么不同呢?
其实前面的代码等价于这样的:
var a = undefined;
alert(a);
也就是说,当声明变量而不赋值时,JS会给变量传一个undefined值,注意,这是个“值”,说明a已经有值了,这个值就叫“未定义”。
而后面的直接alert,变量从没有出现过,也就是说这才是真正的未定义。
简单的说:JS中不存在没有值的变量,变量声明的时候就赋值了。
然后我们看下面的代码:
alert(a);
var a = 1;
这个代码会报错吗?因为在alert的时候变量a还没来得及出现呀。
但是这样居然没有报错,而是弹出了undefined值。表明变量a已经存在了,只是值却不是我们想要的,而是undefined。这又是个什么问题呢?
因为var 变量声明和函数声明一样,会提前,其实上面的代码是这样的:
var a;
alert(a);
a = 1;
这么一来就懂了。
所以,这个问题的关键在于:var 声明会提前到作用域顶端,但附值却不会———好纠结的设定,不知道为什么要这么搞。个人觉得这是JS的一个缺陷。
现在有一种代码习惯,主张把变量声明一律放在作用域前方,大概就是考虑到这个——反正就算你不写在前方,JS也会提前到前方。
现在放出文首问题的答案:
只会弹出两个alert,而if里面的alert不会执行,因为var声明的提前性,导致真正的代码是这个样子:
var aa;
if (!("aa" in window)) {
alert('oh my god');
aa = 1;
}
alert("aa" in window);
alert(aa);
虽然aa为空,但用'aa' in window判断时会为真,因为a确实存在了,而值是undefined。所以if代码不会执行。后面两个alert我就不说了。
个人感觉这是一个很无厘头的问题,我们应该了解他的原因,但鄙视他这种陷阱。
上面这个问题也是我写这篇文章的缘由,这段代码是我从一篇网文里看到的,但他里面没有答案,我百撕不得骑姐,跑到stackoverflow上去问了才搞清楚。答案就是这篇文章。
但这是很基础的问题啊其实!!!
哈哈,原谅我,后面还有一个问题:
var b = {}
alert(b.aa);
alert(b.aa.bb);
这也是一种声明变量的方式,那么,这段代码会报错吗?为什么?