# JS Tip of the Day: The Deal With Prototypes

**URL:** <https://forum.kirupa.com/t/js-tip-of-the-day-the-deal-with-prototypes/643123>\
**Category:** web dev\
**Created:** [April 13, 2020, 12:54pm UTC](https://forum.kirupa.com/t/js-tip-of-the-day-the-deal-with-prototypes/643123 "2020-04-13T12:54:38Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [April 13, 2020, 12:54pm UTC](https://forum.kirupa.com/t/js-tip-of-the-day-the-deal-with-prototypes/643123/1 "2020-04-13T12:54:38Z")

</div>

**The Deal With Prototypes**  
Level: Beginner

Prototypes in JavaScript are objects that other objects look to when they can’t find properties that are being requested of them. If the object doesn’t have the property itself, it can instead use the value of that property in its associated prototype.

You can set the prototype for an object using `Object.setPrototypeOf()`.

```javascript
let me = {};
let friend = { answer: 42 };
console.log(me.answer); // undefined

Object.setPrototypeOf(me, friend);
// (me's prototype is now friend)

console.log(me.answer); // 42 (taken from friend)

```

Prototypes are the mechanism by which JavaScript handles object inheritance. In the example above, the `me` object was set to inherit from the `friend` object. By inheriting from `friend`, `me` has access to all of the properties in `friend`.

Whenever you create a new object normally, that object will already inherit values from the Object type. This includes methods like `toString()`.

```javascript
let empty = {};
console.log(empty.toString()); // [object Object]
// (toString is inherited from empty's default prototype)

```

When an object inherits properties from its prototype, it also inherits the properties in its prototype’s prototype since prototype objects will also look to their own prototypes if a property is being accessed that they don’t have. This creates the _prototype chain_. In the earlier example where `me`'s prototype was set to `friend`, `me` still had access to all of the values inherited from the Object type because `friend` inherits from it by default.

```javascript
let me = {};
let friend = { answer: 42 };
Object.setPrototypeOf(me, friend);
console.log(me.toString()); // [object Object]
// (me's toString inherited from friend
// which inherited it from the Object type)

```

New objects can be created with a specific prototype already set using `Object.create()`.

```javascript
let friend = { answer: 42 };
let me = Object.create(friend);
console.log(me.answer); // 42

```

To get the prototype associated with an object, use `Object.getPrototypeOf()`.

```javascript
let friend = { answer: 42 };
let me = Object.create(friend);
console.log(Object.getPrototypeOf(me) === friend); // true

```

There’s also an ` __proto__ ` accessor property (inherited from the Object type), but it’s use is not recommended. However, when digging through object hierarchies in debuggers like the one used in chrome, you’ll see this identifier used to provide access to the prototype of an object so it’s good to know.

```javascript
let me = {};
let friend = { answer: 42 };
me. __proto__ = friend;
console.log(me.answer); // 42
console.log(Object.getPrototypeOf(me) === me. __proto__ ); // true

```

Object prototypes must be an object or `null`. Non-null primitive values are not allowed. If you create an object with a `null` prototype (or set it to `null` through `Object.setPrototypeOf()`) it will not have access to any of its normally inherited properties.

```javascript
let reallyEmpty = Object.create(null);
console.log(reallyEmpty.toString()); // TypeError: not a function

```

In this particular case, ` __proto__ ` would also fail to work since it is inherited much like `toString()` is.

```javascript
let reallyEmpty = Object.create(null);
console.log(reallyEmpty. __proto__ ); // undefined (should be null)
let lessEmpty = { glassHalfFull: true };
reallyEmpty. __proto__ = lessEmpty; // (does not set prototype)
console.log(Object.getPrototypeOf(reallyEmpty)); // null

```

The actual prototype of an object is stored in an internal slot referred to as `[[Prototype]]` which is not accessible directly. Some objects have a `prototype` property, but it does not represent the prototype of its owner. The `prototype` property exists on constructor functions (or any function that _can_ be a constructor) and is the object used as the prototype for the instances that constructor creates.

```javascript
let arr = new Array(); // arr prototype set to Array.prototype
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true

```

For objects created with literal syntax, the same applies even though you’re not using `new` explicitly. For example, `{}` creates a `new Object()`, `[]` creates a `new Array()`, and `/pattern/` creates a `new RegExp(pattern)`.

```javascript
let arr = []; // same as new Array()
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true

```

So when we say an object inherits from the Object type, it’s inheriting from `Object.prototype`.

```javascript
let obj = {}; // same as new Object()
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true

```

In creating your own constructor function, it is automatically given a `prototype` property which is a normal object inheriting from `Object.prototype`.

```javascript
function Person () {} // (constructor function)
console.log(typeof Person.prototype); // object
console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype);
// true

```

Using a constructor to create a new object creates a new object that inherits from the constructor’s `prototype` which in turn inherits from `Object.prototype` setting up the inheritance chain for that object.

```javascript
function Person () {}
let me = new Person();
console.log(Object.getPrototypeOf(me) === Person.prototype); // true
console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype);
// true
console.log(me.toString()); // [object Object]
// (me's toString inherited from Person.prototype
// which inherited it from Object.prototype)

```

A constructor’s `prototype` is where you’d store shared methods. Each instance created by the constructor would have access to the methods defined there because each instance inherits from the same `prototype` object that’s defined in the constructor.

```javascript
function Person () {}
Person.prototype.getAnswer = function () {
    return 42;
}
let me = new Person();
console.log(me.getAnswer()); // 42
let myEvilClone = new Person();
console.log(friend.getAnswer()); // 42

```

The `class` syntax allows you to do the same thing in a more concise manner. The result is the same: a constructor function that creates object’s that inherits from the class’s (constructor’s) `prototype` object.

```javascript
class Person {
    getAnswer () { // defined on prototype
        return 42;
    }
}
console.log(typeof Person.prototype.getAnswer); // function

let me = new Person();
console.log(Object.getPrototypeOf(me) === Person.prototype); // true
console.log(me.getAnswer()); // 42

```

With classes, you can also easily extend other classes. This will add the extended class’s `prototype` to the prototype chain of the instances it creates.

```javascript
class Person {
    getAnswer () {
        return 42;
    }
}
class SmartPerson extends Person {
    getSmartAnswer () {
        return 'Two score and two';
    }
}

let me = new SmartPerson();
console.log(Object.getPrototypeOf(me) === SmartPerson.prototype);
// true
console.log(Object.getPrototypeOf(SmartPerson.prototype) === Person.prototype);
// true
console.log(me.getAnswer()); // 42 (from Person.prototype)
console.log(me.getSmartAnswer());
// Two score and two (from SmartPerson.prototype)

```

Classes are likely going to be the primary means by which you take advantage of prototypes in JavaScript. While you can use `Object.setPrototypeOf()` to change an object’s prototype, it’s not common to do so and can even have a negative impact on performance. You generally want to create new objects with their prototype already in place and constructors created with `class` are an easy and convenient way to do so.

While this has been a pretty quick and basic overview of prototypes in JavaScript, it can be a difficult concept to get your head wrapped around. If you don’t get it right away, that’s ok. It may take some time.

More info:

- [Object.setPrototypeOf on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf)
- [Object.getPrototypeOf on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf)
- [\_\_proto\_\_ on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto)
- [Object.create on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
- [Prototypes on MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes)
- [Inheritance on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)
- [Classes on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
