1

I'm using classes in ES2015 identical to the snippet below:

class ProfileManager{
  constructor($http){
    this._http = $http;
    this.profile = {};
    }

  getUser(profile){
     this._http(`/api/users/${user.id}`).then(function(response){
        this.profile = response.data;    
        /*
         * Results in exception because "this uses the function's
         * "this" instead of the class' "this"
         */
     });
 }

I know I can remedy this by creating a profile variable outside of the class and using it in the class, but I was wondering if there was a cleaner or more preferred way to use class properties inside of a nested function or callback.

mikeyGlitz
  • 423
  • 3
  • 13

1 Answers1

4

ES6 arrow functions do not override this

class ProfileManager {
  constructor($http) {
    this._http = $http;
    this.profile = {};
  }

  getUser(profile) {
     this._http(`/api/users/${user.id}`).then((response) => {
        this.profile = response.data; 
     });
 }
Coloured Panda
  • 3,293
  • 3
  • 20
  • 30
  • I forgot to mention that this is on client-side scripts which are being transpiled with babel to port ES2015 to ES5. Would the arrow functions not creating any scope still apply in this case? – mikeyGlitz Jul 28 '16 at 11:13
  • 1
    @mikeyGlitz If its transpiled, it will create an additional variable. No way to do this in ES5 – Coloured Panda Jul 28 '16 at 11:15
  • @Kaspars: Yes, there's a way to do this in ES5: `Function#bind`. But Babel will use a variable, as you say. mikey - The variable isn't a problem at all. Kaspar's answer is definitely how you want to do this. Note that if you only have one argument to the arrow function, the `()` around it are optional: `.then(response => {` – T.J. Crowder Jul 28 '16 at 11:17
  • It's more of a personal preference, but if the arrow functions spans for more than one line I keep the parentheses. – Coloured Panda Jul 28 '16 at 11:19
  • @Kaspars: I think you're talking about the curly braces (`{}`). I'm talking about the `()` around the arguments (but with a single argument, it is indeed a personal preference). – T.J. Crowder Jul 28 '16 at 11:19
  • 1
    @mikeyGlitz the beautify of babel is that you don't need to think about *how* it does it is in ES5. Just write the ES6 and trust it will work. If you're curious, check out [their repl](https://babeljs.io/repl/#?evaluate=true&lineWrap=false&presets=es2015%2Creact%2Cstage-0%2Cstage-2&code=class%20ProfileManager%20%7B%0D%0A%20%20getUser(profile)%7B%0D%0A%20%20%20%20%20_http(%60%2Fapi%2Fusers%2F%24%7Buser.id%7D%60).then(response%20%3D%3E%20%7B%0D%0A%20%20%20%20%20%20%20%20profile%20%3D%20response.data%3B%20%20%20%20%0D%0A%20%20%20%20%20%7D)%3B%0D%0A%20%7D%0D%0A%7D) – David Gilbertson Jul 28 '16 at 11:20
  • 1
    @T.J.Crowder I understood what you mean. – Coloured Panda Jul 28 '16 at 11:20
  • I'd imagine it would transpile to `(function(response) { /* .. */ }.bind(this))`. – Nebula Jul 28 '16 at 12:51
  • Tested it. Thanks for the arrow function. Seems that transpiling arrow functions through Babel preserves the expected behavior. – mikeyGlitz Aug 16 '16 at 12:50