Categories
JavaScript Best Practices

Better JavaScript — Prototypes

Spread the love

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at ways to improve our JavaScript code.

Object.getPrototypeOf or proto

Since ES6, __proto__ has become a standard property of an object.

We can get and set it like any other property.

For instance, we can write:

const obj = {};

console.log(obj.__proto__);

to get the prototype of obj .

We get the object’s prototype with the __proto__ property.

We can set it by writing:

const obj = {};
obj.__proto__ = {
  foo: 1
};

console.log(obj.__proto__);

and we get {foo: 1} as the prototype.

If we want to create an object with a prototype, we can also call Object.create with a prototype.

So we can write:

const obj = Object.create({
  foo: 1
})

and we get the same result.

We cal also use the Object.getPrototypeOf method to get the prototype of an object.

For instance, we can write:

Object.getPrototypeOf(obj)

and we get the same result as getting the __proto__ property.

The __proto__ property is standard, so we can safely use it to get and set the prototype.

Make Constructors new-Agnostic

If we’re creating a constructor function, then we may be able to call it as a function.

For instance, if we have:

function Person(name) {
  this.name = name;
}

const p = Person('james');
console.log(this.name)

Then this is the global object and the name property has value 'james' .

This is definitely not what we want.

If we have strict mode, then this would be undefined at the top level, so we can’t create global variables accidentally.

If we have:

function Person(name) {
  "use strict";
  this.name = name;
}

const p = Person('james');

Then we get the error ‘Uncaught TypeError: Cannot set property ‘name’ of undefined’.

This provides us with some protection from call constructors as a regular function.

To make the check more robust, we can add an instance check into the constructor:

function Person(name) {
  if (!(this instanceof Person)) {
    return new Person(name);
  }
  this.name = name;
}

This way, with or without new , we still get the Person instance returned.

The best way is to use the class syntax.

So we can rewrite the constructor to:

class Person {
  constructor(name) {
    this.name = name;
  }
}

This way, if we call Person without new , we get the error ‘Uncaught TypeError: Class constructor Person cannot be invoked without ‘new’’.

Conclusion

There’re various ways to get and set the prototype.

Also, the class syntax is the most robust way to create a constructor.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *