DEV Community

aurel kurtula
aurel kurtula

Posted on

What is this thing called this?

The easiest way to describe this is that it refers to the object it's assigned when called. For example, consider this object:

const song = {
  title: 'What is this thing called love',
  writer: 'Cole Porter',
  artist: 'Elsie Carlisle',
  performed_by: function(){
    return this.artist
  }
}
Enter fullscreen mode Exit fullscreen mode

When song.performed_by() method is called, this refers to song. But before we actually execute the code, this refers to nothing.

Consider the following two lines:

console.log(this.someVariableName)
console.log(someVariableName)
Enter fullscreen mode Exit fullscreen mode

The first line outputs undefined and the second throws an error, telling us that someVariableName is undefined. If we define the variable without passing it a value, the output is the same in both cases

console.log(this.someVariableName)
let someVariableName;
console.log(someVariableName)
Enter fullscreen mode Exit fullscreen mode

Which tells us that this truly is waiting to be assigned to something.

Changing the context of this

A lot of people have sang the song over the years, let me tell you my current favorite versions:

let performers = [
  {
    artist: 'sant andreu jazz band',
    listen_at: 'v=kZS2Kx1Hr9I'
  },
  {
    artist: 'Rebecca Ferguson',
    listen_at: 'v=O0FwMORV2Og'
  }
]
Enter fullscreen mode Exit fullscreen mode

When I run song.performed_by I want one of the above artists to be returned! We do this by using call, apply or even bind.

This is my favorite version of that song:

song.performed_by.call(performers[1])
//or
song.performed_by.apply(performers[1])
Enter fullscreen mode Exit fullscreen mode

this in performed_by refers to another object, and so the output of the above code is Rebecca Ferguson.

The difference between call and apply is how we pass arguments. In the above scenario there's no difference, but if we were to pass arguments, apply passes them as an array.

Lets do another example

Let's change the code a little bit so that we return the title and the artist.

let song = {
  ...
  performed_by: function(){
    return `${this.title} by ${this.artist}`
  }
}
let performers = [
  {
    artist: 'sant andreu jazz band',
    listen_at: 'v=kZS2Kx1Hr9I'
  },
  {
    artist: 'Rebecca Ferguson',
    listen_at: 'v=O0FwMORV2Og'
  }
]
Enter fullscreen mode Exit fullscreen mode

Running song.performed_by() will return the title and the song. But running song.performed_by.call(performers[0]) will return undefined by sant andreu jazz band, that's because performers[0] object doesn't have a title. Let's modify the code.

let song = {
  ...
  performed_by: function(value){
    let title = this.title ? this.title : value
    return `${title} by ${this.artist}`
  }
}
Enter fullscreen mode Exit fullscreen mode

We can add the title as an argument

song.performed_by.call(performers[0], 'What is this thing called love')
Enter fullscreen mode Exit fullscreen mode

If we use apply the title would have to be passed as an array (and clearly, we'd have to reference it as title[0]

song.performed_by.call(performers[0], ['What is this thing called love'])
Enter fullscreen mode Exit fullscreen mode

Using bind

bind is similar to call but used when we want to assign this to an object without calling it

let announcement = function(title){
    return `${title} by ${this.artist}`
}.bind(performers[0])
announcement('What is this thing called love')
Enter fullscreen mode Exit fullscreen mode

In fact, the above snippet perfectly demonstrates the difference between call and bind

let announcementFunction = function(title){ ... }.bind(performers[0])
let announcementValue = function(title){ ... }.call(performers[0])
Enter fullscreen mode Exit fullscreen mode

Because of call the anonymous function has executed and the value is attached to announcementValue

Useful places to use bind might be on event listeners

document.querySelector('a').addEventListener('click', theMan.bind(song) )
Enter fullscreen mode Exit fullscreen mode

Then we create theMan which would take anything inside the song object

const band = function(){
    return `${this.artist} band`
}.bind(performers[0])
function theMan(e){
    console.log(`${this.writer} wrote a great song 
        and the girls from ${band()} sing an amazing cover`)
}
Enter fullscreen mode Exit fullscreen mode

When we click the anchor tag, we get the message Cole Porter wrote a great song and the girls from sant andreu jazz band sing an amazing cover


That's it, thanks for reading. Also, if you are anything like me when it comes to music, you'll like the youtube links I listed

Top comments (0)