// 思考下面代碼運行結果
print(); // 輸出print
function print () {
console.log('print');
}
...
print(); // 無輸出
var print = function () {
console.log('print');
}
...
print(); // 報錯print is not defined
let print = function () {
console.log('print');
}
第一段代碼可以運行并打印出結果是因為js解析時會把函數提升解析,所以雖然我們是在函數定義之前發生的調用,但一樣可以調用成功
第二段無輸出,是因為按函數表達式聲明,一樣存在提升的問題,但這時瀏覽器提升的變量,所以這時會先定義print為undefined
第三段原因是因為我們使用了let,let不存在變量提升,所以調用報錯
一般情況下我們都是使用let去定義各種變量,但是為了兼容性,我們會使用babel對代碼進行轉碼,轉碼后神奇的事情就出現了
'use strict';
print();
var print = function print() {
console.log('print');
};
這時的代碼就會變成和第二段代碼一樣,可以運行了,這個例子不是很正常的例子,因為錯誤明顯,但在瀏覽器完全支持es6之前,我們還是要注意考慮變量提升的問題,雖然你用了let,但編譯器還是會把它轉為var,另外再思考下,為什么babel在對一個匿名函數表達式進行轉換時,會加一個函數名呢?
// 匿名函數表達式
var add = function (a, b) {
return a + b;
}
...
// 指定函數名的表達式
var add = function my_add (a, b) {
return a + b;
}
我感覺這個地方是主要是為了方便調試,比如我們在控制臺輸入add
// 匿名函數表達式的控制臺輸出
? (a, b) {
return a + b;
}
...
// 指定函數名的表達式
? my_add(a, b) {
return a + b;
}
在現在這個簡單函數我們當然可以一眼就看明白這些函數干什么的,但是如果函數很復雜呢,你還能直接明白這個函數是做什么?所以給函數加上一個描述的名詞會方便你的調試,我猜測這也是為啥babel進行轉換時會加上函數名的原因,這點在github上的一個討論也驗證了這個問題