// 思考下面代码运行结果
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上的一个讨论也验证了这个问题