Yes, parameters are hoisted.
When a function is called, each declaration in the function body (var
, let
, const
, and function declarations) is instantiated in the environment record for that execution context. Each formal parameter is also added to the environment record in the same way ([9.2.10 21.c.i and 9.2.10 28.e.i.2]). The full process is described in section 9.2.10 of the spec.
Formal parameters and function declarations are both initialised (note: not "instantiated") during the abstract operation called FunctionDeclarationInstantiation. All other bindings are initialized during evaluation of the function body.
This means that formal parameter bindings are added into the same logical location, in the same way, as those of function body declarations ie. var
, let
, const
, and function declarations (all of which are hoisted, by the way). And it means that formal parameter bindings are initialized in the same way as function declarations (ie. that their corresponding value is set at the top of the function).
Hoisting is a function of the time and place an identifier binding is instantiated. Formal parameter bindings are instantiated (and initialized) in the same way as function declarations. We know function declarations are hoisted, therefore parameter bindings are hoisted. QED.
Prior to ES2015 this hoisting was, as far as I know, invisible, because function parameters are already at the very top of a function. However, parameter default value initializer syntax was added in ES2015, making the hoisting visible in userland.
If formal parameters were not hoisted then the following code would not throw "Uncaught ReferenceError: Cannot access 'x' before initialization"
because the default parameter value for z
would refer to the outer x
:
var x = 'global'
(function(y, z = x, x) {}()) // "Uncaught ReferenceError: Cannot access 'x' before initialization"
Your comment says that 'assuming that parameters are hoisted, x
would [be initialized to] "undefined", and as a result the error would not occur as x
is already initialized'. Your implication is that hoisting could also be used to explain the absence of an error. This is true, but it does not therefore follow that if an error is observed, hoisting cannot be occurring. Indeed, we can see hoisting is occurring because, as specified in the error message, x
in z = x
is taken to refer to formal parameter x
which is declared later in the program text. The only way this is possible is for hoisting to have occurred.