> 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/val/obj/prop/access/chaining-rules.md).

# chaining rules

[JS](/web/js.md) ⟩ [value](/web/js/val.md) ⟩ [object](/web/js/val/obj.md) ⟩ [accessing properties](/web/js/val/obj/prop/access.md) ⟩ chaining rules

{% hint style="success" %}
all <mark style="color:purple;">**chaining rules**</mark> are <mark style="color:yellow;">**depicted**</mark> in the following diagrams.
{% endhint %}

{% tabs %}
{% tab title="🗺️ 圖表" %} <img src="https://2527454625-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MfvEFZnSBhKT6fJmus0%2Fuploads%2FaCI93dtj9qTXG9vfk7mE%2Fchaining.rules.svg?alt=media&amp;token=9d1b3396-e46e-4887-8636-73333d9344a6" alt="" class="gitbook-drawing">

<img src="https://2527454625-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MfvEFZnSBhKT6fJmus0%2Fuploads%2Fauv2rCR82rzf4SpIfZxw%2Foptional.invocation.svg?alt=media&amp;token=dd9bbf5b-d0c4-4a5b-9152-86836a984ff0" alt="" class="gitbook-drawing">
{% endtab %}

{% tab title="💈範例" %} <img src="https://2527454625-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MfvEFZnSBhKT6fJmus0%2Fuploads%2FzfLYK92df3PTOnnLD9qi%2Fchaining.example.001.svg?alt=media&amp;token=5be6d2aa-53d5-4959-90a0-2f1c910ce8ed" alt="chaining example 001" class="gitbook-drawing">

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

```javascript
const { log } = console;

// ⭐ test if `x` is nullish
function isNullish(x) {
    return x === undefined || x === null;
}

// ⭐ about ` a . b ?. c . d ?. e `
testAllCases({ logErrorMessage: false });

// ⭐ test all cases
function testAllCases({
    logErrorMessage = false,
} = {}) {

    // counts
    let nullishCount = 0;
    let nonnullishCount = 0;
    let errorCount = 0;

    // all cases: about ` a . b ?. c . d ?. e `
    const cases = [
        null,
        { b: null },
        { b: { c: null } },
        { b: { c: { d: null } } },
        { b: { c: { d: { e: null } } } },
        { b: { c: { d: { e: 'hi' } } } },
    ];

    // iterate over all cases
    for (const [i, a] of cases.entries()) {
        try {
            const value = a.b?.c.d?.e;
            const nullish = isNullish(value);
            nullish ? nullishCount += 1 : nonnullishCount += 1;
            log(`case ${i + 1}: ${value} (${nullish ? 'N' : 'NN'})`);
        } catch (err) {
            log(`case ${i + 1}: ⛔ ${err.name}${logErrorMessage ? `: ${err.message}` : ''}`);
            errorCount += 1;
        }
    }

    // summary
    log(` cases: ${cases.length}  │  N    NN            // N : nullish`);
    log(`───────────┽────────────         // NN: non-nullish`);
    log(`• live: ${nullishCount + nonnullishCount}  │  ${nullishCount}    ${nonnullishCount}`);
    log(`• dead: ${errorCount}  │`);
    
}

// case 1: ⛔ TypeError
// case 2: undefined (N)
// case 3: ⛔ TypeError
// case 4: undefined (N)
// case 5: null (N)
// case 6: hi (NN)

//  cases: 6  │  N    NN            // N : nullish
// ───────────┽────────────         // NN: non-nullish
// • live: 4  │  3    1
// • dead: 2  │
```

{% endtab %}

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

* :sparkles:[jane.boyfriend?.money.more](/web/js/val/obj/prop/access/chaining-rules/jane.boyfriend-.money.more.md)
  {% endtab %}

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

* <mark style="color:yellow;">**chaining options**</mark>
  * [dot notation (.)](/web/js/val/obj/prop/access/dot-notation-..md)
  * [bracket notation \[\]](/web/js/val/obj/prop/access/bracket-notation.md)
  * [optional chaining (?., ?.\[\])](/web/js/val/obj/prop/access/optional-chaining.md)
  * [optional invocation ?.()](/web/js/val/obj/prop/access/optional-invocation-..md)
* :no\_entry: <mark style="color:yellow;">**possible**</mark>**&#x20;**<mark style="color:red;">**errors**</mark><mark style="color:yellow;">**：**</mark>
  * [<mark style="color:red;">**ReferenceError**</mark>](/web/js/err/ref.md)：[<mark style="color:yellow;">**'xxx' is not defined**</mark>](/web/js/err/ref/not-defined.md):exclamation: (:point\_right:[undeclared identifier](/web/js/grammar/token/id/undeclared.md))
  * [<mark style="color:red;">**SyntaxError**</mark>](/web/js/err/syntax.md)：[<mark style="color:yellow;">**unexpected number**</mark>](/web/js/err/syntax/unexpected-number.md):exclamation: (:point\_right: needs valid [identifier](/web/js/grammar/token/id.md))
  * [<mark style="color:red;">**TypeError**</mark>](/web/js/err/type.md)：[<mark style="color:yellow;">**cannot read properties of nullish**</mark>](/web/js/err/type/cannot-read-properties-of-nullish.md):exclamation: (:point\_right:[nullish](/web/js/val/prim/nullish.md))
    {% endtab %}
    {% endtabs %}
