Object-Oriented JavaScript — Prototypes, Call, and Apply

John Au-Yeung - Jan 24 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at prototypes, call , and apply .

Function Prototypes

Functions have a special prototype property that has items that are shared between all instances of the constructor function.

For instance, we can write:

function F() {}

F.prototype = {
  name: 'james',
  say() {
    return `I am ${this.nam}`;
  }
};
Enter fullscreen mode Exit fullscreen mode

Then if we create 2 instances of F :

const foo = new F();
const bar = new F();
console.log(foo, bar);
Enter fullscreen mode Exit fullscreen mode

We see that both foo and bar have the same properties.

The say method also does the same thing.

Methods of Function Objects

Function objects have their own methods.

For instance, functions have the toString method to return the string with the code of the function.

So if we have:

function add(a, b, c) {
  return a + b + c;
}

console.log(add.toString());
Enter fullscreen mode Exit fullscreen mode

We get:

"function add(a, b, c) {
  return a + b + c;
}"
Enter fullscreen mode Exit fullscreen mode

logged.

Call and Apply

Functions have the call and apply method to let us run functions, set the value of this and pass arguments to it.

For instance, if we have:

const obj = {
  name: 'james',
  say(who) {
    return `${this.name} is ${who}`;
  }
};
Enter fullscreen mode Exit fullscreen mode

Then we can call say with call by writing:

const a = obj.say.call({
  name: 'mary'
}, 'female');
Enter fullscreen mode Exit fullscreen mode

Then a is 'mary is female’ .

We set this to:

{
  name: 'mary'
}
Enter fullscreen mode Exit fullscreen mode

so this.name is 'mary' .

The 2nd argument is the argument for say , so who is 'female' .

We can also call apply by doing the same thing, except that the arguments of the function are in the array.

For instance, we can write:

const obj = {
  name: 'james',
  say(who) {
    return `${this.name} is ${who}`;
  }
};

const a = obj.say.apply({
  name: 'mary'
}, ['female']);
Enter fullscreen mode Exit fullscreen mode

and we get the same thing.

Lexical this in Arrow Functions

this is a dynamic object that changes according to its context.

Arrow functions don’t bind to its own value of this .

So if we have:

const obj = {
  prefix: "Hello",
  greet(names) {
    names.forEach(function(name) {
      console.log(`${this.prefix} ${name}`);
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

We’ll get an error with the greet method since this is the callback function, so it doesn’t have the prefix property.

But if we use an arrow function:

const obj = {
  prefix: "Hello",
  greet(names) {
    names.forEach((name) => {
      console.log(`${this.prefix} ${name}`);
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

Then the function works properly since it doesn’t bind to its own value of this .

Inferring Object Types

The toString method of Object.prototype gives us the class name that’s used to create an object.

For instance, we can write:

Object.prototype.toString.call({});
Enter fullscreen mode Exit fullscreen mode

And get:

"[object Object]"
Enter fullscreen mode Exit fullscreen mode

And if we write:

Object.prototype.toString.call([]);
Enter fullscreen mode Exit fullscreen mode

We get:

"[object Array]"
Enter fullscreen mode Exit fullscreen mode

We can use call with the toString method by writing:

Array.prototype.toString.call([1, 2, 3]);
Enter fullscreen mode Exit fullscreen mode

We get:

"1,2,3"
Enter fullscreen mode Exit fullscreen mode

This is the same as:

[1, 2, 3].toString()
Enter fullscreen mode Exit fullscreen mode

Conclusion

The call and apply methods let us call functions with different values of this and arguments.

Also, the prototype has properties that are shared between all constructor instances.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .