0

How can we set up 'self' with when using 'class'?

I've seen the 'self' variable to get set up for more predictable 'this' usage in javascript classes using the 'function' class declaration. How can we do this with the 'class' declaration?

Function VS Class declarations

// Using the 'function' declaration
function Apple (type) {
    var self = this
    self.type = type
    self.color = "red"
    self.getInfo = function() {
        return self.color + ' ' + self.type + ' apple'
    };
}

// Using the 'class' declaration
class Apple2 {
    constructor(type){
        var self = this
        self.type = type
        self.color = "red"
    }
    getInfo () {
        return self.color + ' ' + self.type + ' apple'
    }
}
let ap = new Apple('Granny')
let ap2 = new Apple2('Jazz')
console.log(ap.getInfo(), ap2.getInfo())
// prints 'red Granny apple undefined undefined apple'

Edit:

It looks like creating the 'self' variable before the constructor works in the chrome console actually, but webpack is throwing an error for it:

// Using the 'class' declaration
class Apple2 {
    self = this
    constructor(type){

        self.type = type
        self.color = "red"
    }
    getInfo () {
        return self.color + ' ' + self.type + ' apple'
    }
}
console.log(new Apple2('Jazz').getInfo())
Mosè Raguzzini
  • 15,399
  • 1
  • 31
  • 43
Jesse Reza Khorasanee
  • 3,140
  • 4
  • 36
  • 53
  • 2
    If you always use arrow functions in a class then using `this` isn't as problematic the way it is with standard functions. Arrow functions have no explicit this so in gneral the context will usually be the class itself. There are caveats though – charlietfl Apr 04 '19 at 23:19
  • Thanks for the recommendation, I didn't realise _this_. Do you have a link to what the caveats could be? – Jesse Reza Khorasanee Apr 04 '19 at 23:24
  • 1
    Yes an example would be passing a class instance method as reference like : `someElement.addEventlistener('click', classInstance.someMethod)`. The `this` would be the element not the class instance unless you did `someElement.addEventlistener('click', classInstance.someMethod.bind(classInstance))` – charlietfl Apr 04 '19 at 23:27
  • 2
    Important to realize that when you write a class method... it is actually added to the prototype...not as direct object property. No the same as `self.getInfo` in the function approach – charlietfl Apr 04 '19 at 23:36

1 Answers1

1

The correct way with classes is to not alias this:

class Apple2 {
  constructor(type) {
    this.type = type
    this.color = 'red'
  }

  getInfo() {
    return `${this.color} ${this.type} apple`
  }
}

console.log(new Apple2('Jazz').getInfo())

The reason is because this is in fact (roughly) equivalent to the following code:

function Apple(type) {
  this.type = type
  this.color = 'red'
}

Apple.prototype.getInfo = function() {
  return this.color + ' ' + this.type + ' apple'
}

console.log(new Apple('Granny').getInfo())

which is why using this works. In fact, even with your original code, the alias was not necessary:

function Apple(type) {
  this.type = type
  this.color = 'red'
  this.getInfo = function() {
    return this.color + ' ' + this.type + ' apple'
  }
}

var apple = new Apple('Granny')

// does not make a difference
console.log(apple.getInfo())

var getInfo = apple.getInfo

// here is where it makes a difference
console.log(getInfo())
// how to fix
console.log(getInfo.call(apple))

For more information on this behavior, see How does the "this" keyword work?

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • Thanks Patrick. I was hoping to get to be able to alias to use with event listeners later, but thank you for writing an answer to help further my understanding. – Jesse Reza Khorasanee Apr 10 '19 at 00:29
  • @JesseRezaKhorasanee Can you update your example with code more like what you're actually trying to get working? – Patrick Roberts Apr 10 '19 at 00:37
  • Nothings broken, I just wanted to be able to alias 'this' when using 'class' declaration if possible. I don't fully understand the edge case workings of 'this' yet, so I alias as it is quite predictable. – Jesse Reza Khorasanee Apr 10 '19 at 00:48