> 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/proto.md).

# prototype

[JS](/web/js.md) ⟩ [value](/web/js/val.md) ⟩ [object](/web/js/val/obj.md) ⟩ prototype

{% hint style="success" %}
desc
{% endhint %}

{% tabs %}
{% tab title="⭐️ 重點" %}
{% hint style="info" %}

* **objects** have a special **hidden property** <mark style="color:purple;">`[[Prototype]]`</mark> that is either <mark style="color:purple;">`null`</mark> or references **another&#x20;**<mark style="color:orange;">**object**</mark> (other types are ignored).
* **that object** is called a “<mark style="color:purple;">**prototype**</mark>”.
* when we access an object's <mark style="color:orange;">**method**</mark>/<mark style="color:orange;">**property**</mark>, and it’s <mark style="color:red;">**missing**</mark>, JavaScript **automatically** takes it from the <mark style="color:purple;">**prototype**</mark>.
  {% endhint %}

{% hint style="success" %} <mark style="color:purple;">**`__proto__`**</mark>&#x20;

* is a [getter/setter](/web/js/val/class/member/getter-setter.md) for <mark style="color:purple;">\[\[Prototype]]</mark> and resides in <mark style="color:orange;">**Object.prototype**</mark>.
* is considered **outdated**, modern methods are:
  * [Object.create(proto, \[descriptors\])](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)&#x20;
  * [Object.getPrototypeOf(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf)&#x20;
  * [Object.setPrototypeOf(obj, proto)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf)&#x20;
* to access <mark style="color:purple;">`[[Prototype]]`</mark>(which is hidden and internal).

```javascript
// ⭐️ `__proto__` is a getter & setter for [[Prototype]]
obj.__proto__            // call getter
obj.__proto__ = proto    // call setter
Object.getPrototypeOf(obj)
Object.setPrototypeOf(obj, proto)
```

{% endhint %}

{% hint style="danger" %}
[prototype chain](/web/js/val/obj/proto/chain.md) <mark style="color:red;">**can't go in circles**</mark>.
{% endhint %}
{% endtab %}

{% tab title="🔴 主題" %}

* [IteratorPrototype](/web/js/iteration/iterator/iteratorprototype.md) - prototype of all built-in [iterator](/web/js/iteration/iterator.md)s.
  {% endtab %}

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

* all <mark style="color:yellow;">**objects**</mark> created by [object literal](/web/js/val/obj/create/obj.md) have the <mark style="color:yellow;">**same**</mark> <mark style="color:purple;">**prototype**</mark> - [**Object.prototype**](/web/js/val/builtin/object/object.prototype.md).
* used in object's prototypal [inheritance](/web/js/val/class/inheritance.md).
* function's [prototype](/web/js/val/func/prototype.md) is used as <mark style="color:orange;">**new**</mark> [Broken mention](broken://pages/c3kdqarPVmCRDuMeH3s5)'s <mark style="color:purple;">\[\[Prototype]]</mark>.
* [super](/web/js/val/class/inheritance/super.md) === [<mark style="color:purple;">**`[[HomeObject]]`**</mark>](/web/js/val/obj/method/home-object.md)<mark style="color:purple;">**`.`**</mark>[<mark style="color:purple;">**`[[Prototype]]`**</mark>](/web/js/val/obj/proto.md)⭐️&#x20;
* <mark style="color:purple;">\[\[Prototype]]</mark> is also cloned by [clone(obj)](/web/appendix/custom/custom-functions/clone-obj.md).
* ["pure" object](/web/js/val/obj/create/object.create/pure-object.md) is an object without <mark style="color:purple;">\[\[Prototype]]</mark> (=== <mark style="color:orange;">**null**</mark>).
  {% endtab %}

{% tab title="💈範例" %}
{% hint style="info" %}
下面的程式碼可以看出幾個特點：

* method (含 getter/setter) 有 <mark style="color:orange;">dynamic</mark> <mark style="color:purple;">**`this`**</mark>，程式碼中的<mark style="color:purple;">**`this`**</mark>指的是誰，要看呼叫者(<mark style="color:yellow;">**caller**</mark>)是誰。

* 如果 method 中<mark style="color:orange;">**參照**</mark>到<mark style="color:purple;">**`this`**</mark>的方法或屬性，這時如果 <mark style="color:yellow;">**caller**</mark> (=<mark style="color:purple;">**`this`**</mark>) <mark style="color:red;">**沒有此方法或屬性**</mark>，那就會<mark style="color:red;">**循著**</mark>**&#x20;**<mark style="color:purple;">**prototype chain**</mark>**&#x20;**<mark style="color:red;">**往上找**</mark>。

* 如果 method 中要<mark style="color:red;">**設定**</mark><mark style="color:purple;">**`this`**</mark>的屬性，這時不管 <mark style="color:yellow;">**caller**</mark> 有沒有此屬性，此屬性<mark style="color:red;">**一定會被設定在**</mark>**&#x20;**<mark style="color:yellow;">**caller**</mark>**&#x20;**<mark style="color:red;">**身上**</mark>，而<mark style="color:red;">**不會**</mark>循著 prototype chain 往上找，這點要特別注意❗️
  {% endhint %}

* [replit](https://replit.com/@pegasusroe/JS-object-method-dynamic-this)

```javascript
const { log } = console;

// ------------------------ user ---------------------------
let user = {
    
    // instance properties
    name   : 'John',
    surname: 'Smith',

    // setter/getter
    set fullName(value) {
	[this.name, this.surname] = value.split(' ');
    },

    get fullName() {
	return `${this.name} ${this.surname}`;
    }
};

// -------------------------- admin -------------------------
let admin = {
    __proto__: user,        // ⭐ admin.__proto__ === user
    isAdmin: true,
};

// ------------------------- test --------------------------
[
    admin.fullName,                    // 📤 get: "John Smith"   (from `admin.__proto__`❗)
    admin.fullName = 'Alice Cooper',   // 🖊️ set: "Alice Cooper" (this === admin❗)
    admin.fullName,                    // 📤 get: "Alice Cooper" (from `admin`❗)
    
    user.fullName,                     // 📤 get: "John Smith"   (from `user`, this === user❗)
    
].forEach(x => log(x));
```

{% endtab %}

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

* MDN ⟩ [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) ⟩
  * [Object.getPrototypeOf()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf)
  * [Object.setPrototypeOf()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf)
  * [Object.create()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
    {% endtab %}

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

* [ ] You Don't Know JS: this & Object Prototypes ⟩ [Chapter 5: Prototypes](https://gist.github.com/kad3nce/9674522)
* [ ] JS.info ⟩&#x20;
  * [ ] [Class inheritance](https://javascript.info/class-inheritance)
  * [x] [Prototypal inheritance](https://javascript.info/prototype-inheritance)
  * [x] [F.prototype](https://javascript.info/function-prototype)
  * [x] [Native prototypes](https://javascript.info/native-prototypes) - Object.prototype, Number.prototype, Array.prototype ...
  * [x] [Prototype methods, objects without **\_\_proto\_\_**](https://javascript.info/prototype-methods)
  * [x] [Class extends Object?](https://javascript.info/static-properties-methods#class-extends-object) - 說明 <mark style="color:orange;">class A</mark> 與 <mark style="color:orange;">class A extends Object</mark> 有何不同 ⭐️
    {% endtab %}
    {% endtabs %}
