> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/web/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/web/js/variable/declare/var/param-by-var.md).

# var can shadow parameter even in strict mode❗️

[JS](/web/js.md) ⟩ [variable](/web/js/variable.md) ⟩ [shadowing](/web/js/variable/shadow.md) ⟩ var can shadow parameter even in strict mode.

{% hint style="warning" %}
[parameter](/web/js/val/func/param.md)(s) <mark style="color:yellow;">**can be shadowed**</mark> by [var](/web/js/variable/declare/var.md):exclamation:
{% endhint %}

{% tabs %}
{% tab title="⭐️ 重點" %}
{% hint style="success" %}
:star: [function declaration](/web/js/val/func/declare.md) <mark style="color:yellow;">**instantiation**</mark>

When an [execution context](https://tc39.es/ecma262/#sec-execution-contexts) is established for evaluating an ECMAScript [function](/web/js/val/func.md)：

* a new [Function Environment Record](https://tc39.es/ecma262/#sec-function-environment-records) is created and bindings for each <mark style="color:yellow;">**formal parameter**</mark> are instantiated in that [Environment Record](https://tc39.es/ecma262/#sec-environment-records).&#x20;
* Each [declaration](/web/js/grammar/declare.md) in the <mark style="color:yellow;">**function body**</mark> is also instantiated.&#x20;
* If the function's <mark style="color:yellow;">**formal parameters**</mark> <mark style="color:red;">**do not**</mark>**&#x20;**<mark style="color:yellow;">**include**</mark> any <mark style="color:yellow;">**default value initializers**</mark> then the <mark style="color:orange;">**body declarations**</mark> are instantiated in the <mark style="color:red;">**same**</mark> [Environment Record](https://tc39.es/ecma262/#sec-environment-records) as the <mark style="color:orange;">**parameters**</mark> :exclamation:
* If <mark style="color:yellow;">**default value initializers**</mark>**&#x20;exist**, a <mark style="color:red;">**second**</mark> [Environment Record](https://tc39.es/ecma262/#sec-environment-records) is created for the <mark style="color:yellow;">**body declarations**</mark> :exclamation:
* Formal <mark style="color:yellow;">**parameters**</mark> and <mark style="color:yellow;">**functions**</mark> are initialized as <mark style="color:yellow;">**part**</mark> of [FunctionDeclarationInstantiation](https://tc39.es/ecma262/#sec-functiondeclarationinstantiation). All <mark style="color:yellow;">**other bindings**</mark> are initialized during <mark style="color:yellow;">**evaluation**</mark> of the <mark style="color:yellow;">**function body**</mark>.

📘 [JS spec](/web/master/ref/js-spec.md) ⟩ [FunctionDeclarationInstantiation](https://tc39.es/ecma262/#sec-functiondeclarationinstantiation)
{% endhint %}
{% endtab %}

{% tab title="💈範例" %}

* replit：[shadowing parameters](https://replit.com/@pegasusroe/shadowing-parameters#index.js)

```javascript
const { log } = console;

let count = 0;

// (*)
// ⭐ "initialization block" in a for-loop
// ---------------------------------------
//   ╭──init───╮
for ( let i = 0 ; i < 3 ; i++ ) {

    // ⭐ for-loop body (block scope) and the "initialization block"
    //    are in different scopes, so we can "shadow" the outer `i`
    //    with a local "let" without any problem.
    let i = 1;
    
    log(i);                    // 1, 1, 1
    if (++count > 3) break;    // prevent infinite loop
}

// ⭐ case 1: (alters parameter directly)
// ---------------------------------------
// • parameter `id` is closed over by `defaultID`.
//
//                ╭─── parameter list ───╮
function doUpdate(id, defaultID = () => id) {
    id = 5;                  // ✅ parameter `id` updated (see (**) below)
    log( defaultID() );
}

// (**)
doUpdate(3);                 // ✅ 5

// ⭐ case 2: (shadows parameter by local "var")
// ----------------------------------------------
//
//                    ╭─── parameter list ───╮
function doesntUpdate(id, defaultID = () => id) {

    // ----------------------0
    //  ❓ weird situation ❓
    // ----------------------0
    
    // ❗ 2.1: can't shadow parameters by "let" variables
    // ----------------------------------------------------------
    // let id = 5;
    //     ^^
    // ⛔ SyntaxError: Identifier 'id' has already been declared
    // ----------------------------------------------------------

    log( defaultID() );      // 3

    // ⭐ 2.2 use "var" instead:
    // -------------------------
    
    var id = 5;              // ❗ this do shadow parameter `id`
    log(id);                 // 5

    log( defaultID() );      // 3
    
    // ----------------------------------------------------------------
    // ⭐ are "parameter list" and "function body" in the same scope ❓
    // ----------------------------------------------------------------
    //
    //   • if so, `var id = 5` should be considered a "redeclaration",
    //     parameter `id` should be updated by the redeclaration, 
    //     but it's NOT, why ❓   (see: (***) below)
    //     (Q: is parameter `i` a "var" ?) 
    // 
    //   • if they're not in the same scope, why can't we shadow 
    //     the (outer) parameter `id` with a local "let", like we
    //     do in a "for-loop"❓  (see: (*) above)
    //
    // ----------------------------------------------------------------

}

// (***)
doesntUpdate(3);             // ❗ (parameter `id` is not updated)
```

{% endtab %}

{% tab title="📘 手冊" %}

* [JS spec](/web/master/ref/js-spec.md) ⟩&#x20;
  * [FunctionDeclarationInstantiation](https://tc39.es/ecma262/#sec-functiondeclarationinstantiation)
  * [Function Environment Record](https://tc39.es/ecma262/#sec-function-environment-records)
    {% endtab %}

{% tab title="👥 相關" %}

* [for](/web/js/grammar/statement/loop/for/for.md) loop
* [closure](/web/js/val/func/closure.md)
* [lexical environment](/web/js/concept/execution-context/lexical-environment.md)
* [parameter](/web/js/val/func/param.md) / [argument](/web/js/val/func/argument.md)
* [strict mode](/web/js/concept/env/js-engine/mode/strict-mode.md)
* :white\_check\_mark:[let can't shadow parameter even in sloppy mode❗️](/web/js/variable/declare/let/let-cant-shadow-param.md)
  {% endtab %}

{% tab title="🗣 討論" %}

* [shadowing parameters by local variables?](https://stackoverflow.com/questions/74154964/shadowing-parameters-by-local-variables) (my question)
* [Where are arguments positioned in the lexical environment?](https://stackoverflow.com/questions/61208843/where-are-arguments-positioned-in-the-lexical-environment) ⭐️
  {% endtab %}

{% tab title="📗 參考" %}

* [ ] [YDKJS: Scope & Closures (v.2)](/web/master/ref/book/you-dont-know-js-series-v.2/ydkjs-scope-and-closures-v.2.md) ⟩ Ch. 8 ⟩ [Parameter Scope](https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/apA.md#parameter-scope)
  {% endtab %}

{% tab title="🚧" %}

* [ ] Function Environment Record
* [x] formal parameter === parameter
* [ ] function body
* [ ] default value initializer
  {% endtab %}
  {% endtabs %}
