JavaScript函数提升场景下“作用域(scope)”的准确定义是什么?
关于JavaScript函数提升中"作用域(scope)"的准确定义
这是个特别棒的问题——函数提升的行为确实会因为作用域类型的不同而产生差异,咱们一步步把它拆解明白:
1. JavaScript里的作用域分类
首先得明确,JS里的作用域主要分三类:
- 全局作用域:代码最外层的作用域,所有没放在函数/代码块里的变量、函数都归属于这里。
- 函数作用域:每个函数声明都会创建自己专属的函数作用域,内部的变量和函数默认只能在这个函数内部访问。
- 块级作用域:从ES6开始,用
{}包裹的代码块(比如if判断、for循环,甚至直接写的独立块)都会创建块级作用域,let、const变量,以及在块里声明的函数,都受这个作用域的约束。
2. 函数提升的核心规则:作用域是提升的边界
函数提升的核心逻辑可以总结为:函数声明会被提升至它所属作用域的顶部,这里的「所属作用域」完全取决于函数声明的位置:
- 如果函数声明在函数作用域的顶层(没有嵌套在任何块里),它会被直接提升到整个函数作用域的顶部。就像你代码里的
zoo函数——它在foo函数的顶层,所以直接提升到foo的最顶部,这也是为什么你调用console.log(zoo)时能拿到完整的函数引用。 - 如果函数声明在块级作用域内部(比如你代码里的
too函数被包裹在{}里),它的提升范围就被限制在这个块级作用域内,绝对不会突破到外层的函数作用域顶部。在块外的位置(比如你写的console.log(too)),这个函数对应的变量虽然会在外部函数作用域里被提前声明,但初始值是undefined,只有当代码执行到这个块的时候,才会把函数赋值给这个变量。
3. 函数提升语境下"作用域"的准确定义
放在函数提升的语境里,「作用域」指的就是当前函数声明所在的最直接的那个作用域:
- 如果函数在全局作用域声明,就提升到全局作用域的顶部;
- 如果在函数作用域的顶层声明,就提升到该函数作用域的顶部;
- 如果在块级作用域内声明,就提升到该块级作用域的顶部,同时会在外部的函数作用域里创建一个初始值为
undefined的变量绑定(这是ES6规范明确的行为,之前ES3/ES5时代块内函数会被提升到函数作用域顶部,属于历史兼容问题,现在已经统一为块级提升规则)。
举个更直观的例子,你的代码其实等价于这样的执行顺序:
// foo函数被提升到全局作用域顶部 function foo() { // zoo函数被提升到foo作用域顶部 function zoo() {console.log("zoo");} // too变量被提升到foo作用域,但初始值是undefined let too; console.log(too); // 输出undefined console.log(zoo); // 输出完整函数 { // too函数被提升到这个块的顶部,赋值给外部的too变量 too = function() {console.log("too");} } } foo();
简单来说,函数提升不会跨越作用域的边界,每个作用域内的函数声明只会在自己的作用域顶部被提升,块级作用域现在是函数提升的有效边界之一。
内容的提问来源于stack exchange,提问作者Richard Hu
相关产品推荐
相关产品推荐

