由于 ES5 和 ES6 在函数提升和函数块级作用域上有巨大差异,所以这里以 ES6 + 浏览器环境为标准。
console.log(fn); // undefined
fn(); // 报错,fn is not a function
{
fn(); // 10
function fn() {
console.log(10);
}
fn(); // 10
}
fn(); // 10
记住这三句(浏览器遵循的 es6 标准)
- 允许在块级作用域内声明函数
- 函数声明(函数名称) 类似于 var,即会提升到全局作用域或函数作用域的头部
- 同时,函数声明(函数整体) 还会提升到所在的块级作用域的头部
所以上面的函数相当于这样
var fn;
console.log(fn); // undefined
fn(); // 报错,fn is not a function
{
fn = function () {
console.log(10);
};
fn(); // 10
fn(); // 10
}
fn(); // 10
前面讨论的一直都是:函数声明 + 浏览器环境
即,function xxx(){} 这种函数声明。而不是 var xxx = function(){} 这种函数表达式。前者,用本文的逻辑去考虑函数的提升和函数的块级作用域;后者,等价于变量的提升和变量的块级作用域。
如果换做严格模式下的 node 环境,那么将严格遵守 es6 标准:函数声明类似于 let。
林秀栋的技术博客