> For the complete documentation index, see [llms.txt](https://xiaoyang-liu.gitbook.io/programming-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xiaoyang-liu.gitbook.io/programming-notes/web-development/javascript-tutorial/the-javascript-language/chapter-8-prototypes-inheritance.md).

# Chapter 8: Prototypes, inheritance

## 8.1 Prototypal inheritance

### \[\[Prototype]]

Objects have a special hidden property `[[Prototype]]` (as named in the specification), that is either null or references another object (prototype).

When we want to read a property from object, and it’s missing, JavaScript automatically takes it from the prototype, which is called “prototypal inheritance”.

To set the internal property, use the special name `__proto__`. (getter/setter for `[[Prototype]]`)

```javascript
rabbit.__proto__ = animal;
```

The references can’t go in circles. Other types of `__proto__` are ignored.

### Writing doesn’t use prototype

The prototype is only used for reading properties. Write/delete operations work directly with the object. (Accessor properties are an exception.)

### The value of “this”

No matter where the method is found: in an object or its prototype. In a method call, `this` is always the object before the dot. Methods are shared, but the object state is not.

### for…in loop

The `for..in` loop iterates over inherited properties. It only lists enumerable properties.

`obj.hasOwnProperty(key)` returns `true` if `obj` has its own (not inherited) property named `key`. This method is stored in the `Object.prototype` object and all of its methods are not enumerable.

## 8.2 F.prototype

If `F.prototype` is an object, then the `new` operator uses it to set `[[Prototype]]` for the new object. Change to this property won't affect the existing objects created by the constructor.

```javascript
function Rabbit(name) {
  this.name = name;
}

Rabbit.prototype = animal;
```

### Default F.prototype, constructor property

The default `prototype` is an object with the only property `constructor` that points back to the function itself. We can use `constructor` property to create a new object with the same constructor.

```javascript
function Rabbit() {}

/* default prototype
Rabbit.prototype = { constructor: Rabbit };
*/

let rabbit = new Rabbit();
let anotherRabbit = new rabbit.constructor();
```

JavaScript itself does not ensure the right `constructor` value. To keep the right `constructor`, we can choose to add/remove properties to the default `prototype` instead of overwriting it as a whole.

## 8.3 Native prototypes

### Object.prototype

```javascript
let obj = {};
alert( obj ); // "[object Object]" ?
```

The string `[object Object]` is generated by the `Object.prototype.toString()` method. There is no more `[[Prototype]]` in the chain above `Object.prototype`.

### Other built-in prototypes

Other built-in objects such as `Array`, `Date`, `Function` and others also keep methods in prototypes. Methods of thee built-ins also reside in the prototypes of their object wrappers.

### Changing native prototypes

```javascript
String.prototype.show = function() {
  alert(this);
};

"BOOM!".show(); // BOOM!
```

Prototypes are global, so it’s easy to get a conflict. There is only one case where modifying native prototypes is approved: polyfilling.

### Borrowing from prototypes

```javascript
let obj = {
  0: "Hello",
  1: "world!",
  length: 2,
};

obj.join = Array.prototype.join;
obj.join(','); // Hello,world!
```

The internal algorithm of the built-in `join` method only cares about the correct indexes and the `length` property. It doesn’t check if the object is indeed an array.

This can also be done by chaning the `__proto__` property of the `obj`, but remember that we only can inherit from one object at a time.

## 8.4 Prototype methods, objects without **proto**

* `Object.create(proto, [descriptors])` – creates an empty object with given proto as `[[Prototype]]` and optional property descriptors.
* `Object.getPrototypeOf(obj)` – returns the `[[Prototype]]` of obj.
* `Object.setPrototypeOf(obj, proto)` – sets the `[[Prototype]]` of obj to proto.

These should be used instead of `__proto__`.

```javascript
let animal = {
  eats: true
};

let rabbit = Object.create(animal, {
  jumps: {
    value: true
  }
});
```

The descriptors are in the same format as the Property flags and descriptors.

This call makes a truly exact copy of `obj`, including all properties: enumerable, non-enumerable, data properties, setters/getters, and the right `[[Prototype]]`.

```javascript
let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
```

### "Very plain" objects

The `__proto__` property is special: it must be either an object or `null`. When the object is used as associative arrays to store key/value pairs, it will cause error if the user assign an object to the `__proto__` key.

`__proto__` is a getter/setter inherited from its prototype, so we can create a plain object by setting its prototype to `null`:

```javascript
let obj = Object.create(null);
```
