Default function arguments not using current scope

# Cyril Auburtin (15 days ago)

I don't understand:

var z=1; var fn = (z = z) => z; fn() // throws ReferenceError: z is not defined
# Cyril Auburtin (15 days ago)

It's rather a name clashing I guess, the error message was just confusing

since this works fine:

var Z=1; var fn = (z = Z) => z; fn() // 1

2018-04-05 10:29 GMT+02:00 Cyril Auburtin <cyril.auburtin at>:

# T.J. Crowder (15 days ago)

On Thu, Apr 5, 2018 at 9:29 AM, Cyril Auburtin <cyril.auburtin at> wrote:

I don't understand:

var z=1; var fn = (z = z) => z; fn()
// throws ReferenceError: z is not defined

SpiderMonkey's error message is a bit clearer here:

ReferenceError: can't access lexical declaration `z' before initialization

Remember that default parameter values have their own scope. In that scope, they have a TDZ (like let and const do in a block) until they're initialized. I believe this is covered in FunctionDeclarationInstantiation Step 28. At the point the default value expression = z is evaluated, the z parameter has been created as an uniniitialized binding (by CreateMutableBinding in 28.f.i.2). Consequently, it tries to get the value of that uninitialized binding, which results in a ReferenceError as described in Table 14 under Environment Records:

GetBindingValue(N, S) - Returns the value of an already existing

binding from an Environment Record. The String value N is the text of the bound name. S is used to identify references originating in strict mode code or that otherwise require strict mode reference semantics. If S is true and the binding does not exist throw a ReferenceError exception. If the binding exists but is uninitialized a ReferenceError is thrown, regardless of the value of S.

(My emphasis.)

E.g., you get that error for the reason you get that same error from:

var z = 42; { console.log(z); let z; }

-- T.J. Crowder

# Cyril Auburtin (15 days ago)

Thanks for the clear explanation

2018-04-05 11:08 GMT+02:00 T.J. Crowder <tj.crowder at>: