探讨一个问题,JavaScript 中,变量可以在使用后声明
,也就是变量可以先使用再声明。
例如如下代码:
//1.先使用变量后申明
console.log(num);
var num = 66;
//2.先调用函数后定义
fn();
function fn() {
console.log('先调用函数后申明');
}
//3.匿名函数先调用后定义会报错
fun();
var fun = function () {
console.log('匿名函数先调用后申明会报错');
}
观察运行结果,按照c语言常识的话,前面两个都应该会报错呢,但是并没有,让人难受的是,情况1 输出undefined ,情况2还执行了,最后一个反而还报错了。
JavaScript的预处理
js
引擎会把js
的执行分为两步,1.预解析 2.代码执行
预解析其实就一句话,js
引擎会把变量申明var
和 函数定义function
,提升到当前作用域
的最前面执行,但是不执行赋值操作。
这样我们就很容易理解上面的问题了。
-
情况1 先使用变量后申明
console.log(num); var num = 66;
解释器预处理的时候,先把声明
var num;
放到当前作用域的最前面执行,但是没有赋值,所以就会输出undefined啦var num;//提升到前面执行 console.log(num);//没有赋值不知道是啥变量,所以输出undefined. var num = 66;
-
情况2 先调用函数后定义
fn(); function fn() { console.log('先调用函数后申明'); }
编译器其实遇到定义函数就会提前到当前作用域最前面定义(不管你的函数在多么后面定义),不会调用函数。
-
情况3 匿名函数先调用后申明会报错
fun(); var fun = function () { console.log('匿名函数先调用后申明会报错'); }
预处理的时候,会把
var fun ;
提升到最前面,但是不执行赋值操作,当你执行fun();
编译器不知道他是函数会报错的。相当于如下代码。
var fun; fun(); var fun = function () { console.log('匿名函数先调用后申明会报错'); }
练习一下
var num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}
分析,js
引擎会把变量申明var
和 函数定义function
,提升到当前作用域
的最前面执行,但是不执行赋值操作。
那么 function fun(){....}
会被提前定义好,里面的var num;
也会提前被申明。值得注意的是这里有两个num
但是作用域不同,执行fun里面的num
是{}里定义num
代码其实可以看成这样子
var num;
function fun() {
var num;
console.log(num);
var num = 20;
}
var num = 10;
fun();
所以输出 undefined。
结语
假期的第五天