偶然看到一个网上一个题目:
function f(){//函数声明 console.log( x ); function x(){} console.log( x ); } f();
Q: 输出什么?
我觉得很简单啊:
undefined;
function x(){};
然鹅,事情并不是这样的:
很显然,两次都打印出了x变量的真实指向→函数体,为什么呢?
为此,我又尝试了函数表达式,结果又是这样的:
function f2(){//函数表达式 console.log( x ); var x = function(){}; console.log( x ); } f2();
这又是为什么呢?于是上网查阅了相关知识和编程指南,得到如下结论:
1.函数声明在声明之前就可用:函数声明是在js预编译阶段就完成的,比如js里司空见惯的全局函数显然是可以在声明之前就调用的,因为js在编译阶段已经将函数声明提前编译完成了;
2.函数内部变量提前声明:表达式是在执行时赋值的,有类似runtime的意思,但js有一个“函数内变量提前声明”的操作,即,在函数内部所有的变量声明会被提到函数头部执行(赋值不提前),所以,在表达式声明前访问会出现undefined,但不会出现unreference。参见《javaScript权威指南》3.8节。
现在上述两个demo的结果就一目了然了,结论1,2分别对应代码片段1,2。
这里的关键只是点是 “函数声明的预编译” 和 “函数内部变量的提前声明” ,带着这些知识点看一些 “怪怪的” 问题就一点也不怪了,哈哈。
——学无止境,may stars guide your way。