首页 > 解决方案 > JavaScript 中的函数参数是否被提升?

问题描述

function foo(a,b){
  return a + b;
}

foo(1,2);

函数参数是否被提升?

函数执行上下文的创建阶段的 variableEnvirnoment 是否看起来像这样:

VE = {
        { 0 : undefined , 1: undefined, length: 2 },
        {a : undefined, b: undefined},
        outer: refToGlobalLE
     }

标签: javascripthoistingexecutioncontext

解决方案


是的,参数被提升了。

调用函数时,函数体中的每个声明(varletconst和函数声明)都会在该执行上下文的环境记录中实例化。每个形式参数也以相同的方式添加到环境记录中([9.2.10 21.ci 和 9.2.10 28.ei2])。整个过程在规范的第 9.2.10 节中描述。

在称为FunctionDeclarationInstantiation的抽象操作期间,形式参数和函数声明都被初始化(注意:不是“实例化”) 。所有其他绑定在函数体的评估过程中被初始化。

这意味着形式参数绑定以与函数体声明相同的方式添加到相同的逻辑位置,即。var, let, const, 和函数声明(顺便说一句,所有这些都被提升了)。这意味着形式参数绑定以与函数声明相同的方式初始化(​​即它们的对应值设置在函数的顶部)。

提升是一个标识符绑定被实例化的时间和地点的函数。形式参数绑定以与函数声明相同的方式实例化(和初始化)。我们知道函数声明被提升,因此参数绑定被提升。QED。

据我所知,在 ES2015 之前,这种提升是不可见的,因为函数参数已经在函数的最顶层。但是,在 ES2015 中添加了参数默认值初始化器语法,使得提升在用户空间中可见。

如果没有提升形式参数,则以下代码不会抛出"Uncaught ReferenceError: Cannot access 'x' before initialization",因为默认参数值z将引用外部x

var x = 'global'
(function(y, z = x, x) {}()) // "Uncaught ReferenceError: Cannot access 'x' before initialization"

您的评论说'假设参数被提升,x将[被初始化为]“未定义”,因此错误不会像x已经初始化的那样发生'。你的意思是提升也可以用来解释没有错误。这是真的,但因此并不意味着如果观察到错误,就不会发生提升。事实上,我们可以看到提升正在发生,因为如错误消息中所述,xinz = x被认为是指x稍后在程序文本中声明的形式参数。唯一可能的方法是提升已经发生。


推荐阅读