转来一篇非常有意思的文章:
Dmitry Baranovskiy 的博客中有篇文章(链接),其中有五段小代码,用来测试是否理解JavaScript 的核心,闭包和作用域。大家先试着给出 alert 语句的输出结果。之后再建一个测试文件,检测你的答案。最后再看看我给的解析。
1
if (!("a" inwindow)) { var a = 1; } alert(a);
2
var a = 1, b = functiona(x) { x && a(--x); }; alert(a);3
function b(x, y, a) { arguments[2] = 10; alert(a); } b(1, 2, 3);4
function a(x) { returnx * 2; } var a; alert(a);5
function a() { alert(this); } a.call(null);
----------------------------------------------------------------------------------------我是分割线----------------------------------------------------------------------------------------
答案与解析:1
答案: undefined。
解析:这个原理叫“变量提升“,简单的说,因为js没有块级作用域,只有函数级作用域,js中的局部变量的声明都会被“提升”至当前作用域的顶端。所以这段代码相当于:
var a; if (!("a" inwindow)) { a = 1; } alert(a);
2
答案:1。
解析:这个我还有点疑问,望高人指导。这段代码涉及到了js解释器解释执行代码的过程,因为js和很多其他语言一样,函数定义可以在函数调用之后,说明了解释器在实际执行代码之前已经做了一个”预编译“操作,这个操作的一个目的就是为所有的函数建立一个”符号表“,正因为在执行代码之前已经建立了这个表,所以函数调用可以放在函数声明之前。因此,实际上函数声明那段代码在代码执行前就执行了,所以后来发现a==1,因为a把函数名覆盖了。
3
答案:10。
解析:这个没什么好说的,这个例子就是说明arguments[2]和a就是同一个对象,而不是一个拷贝。这是arguments的一个特性。
4
答案:就是那个函数。
解析:这个题目比较容易答对,即使没有理解变量提升和函数声明的预编译过程。应该改成这样:
var a = 1; function a() {} alert(a);这就比较有迷惑性了。修改后的答案是 1。因为函数声明是在预编译阶段就执行的,然后被 var a=1给覆盖了。注意预编译是肯定比任何代码(包括变量提升)要早的。
5
答案: window。
解析:这个原因应该是call函数的实现中,对参数的判断是,如果参数为null或undefined,就认为没有传参数,而没有传参数的时候上下文显然应该是window。