1

Lets say I want to assign a class method as a callback, which is better? By better, I really mean for style & readability.

const Foo = class {
  /** @param {!Promise} */
  optionOne(theirPromise) {
    theirPromise(this.myHandler_.bind(this));
  }
  /** @param {!Promise} */
  optionTwo(theirPromise) {
    theirPromise(() => this.myHandler_());
  }
  /** @private */
  myHandler_() {
    // Do something classy
  }
};

I read the arrow function call as cleaner in this case, but if there are a bunch of parameters in the callback, it starts to get silly:

addCallback((a, b, c, d, e, f) => this.myHandler_(a, b, c, d, e, f))

I see the penalty of wrapping in a function, memory mostly, assuming the compiler doesn't trim the call away.

cyrus
  • 671
  • 5
  • 5
  • "memory mostly" --- `.bind` also creates a function. – zerkms Nov 29 '16 at 01:14
  • 1
    That trailing underscore is weird. If you want to focus on readability/conventions, go for `_myHandler` :-) – Bergi Nov 29 '16 at 01:17
  • @zerkms the arrow function forms a closure that is more complicated to handle for the compiler, so there could be implementation differences. I'm not going to guess which is better though. – Bergi Nov 29 '16 at 01:20
  • @zerkms Didn't know `.bind` creates a function. Neat. @Bergi Trailing underscore for private methods is in the Google JS Style Guide: https://google.github.io/styleguide/jsguide.html#naming-method-names – cyrus Nov 29 '16 at 02:19

1 Answers1

4

Style and readability are subjective.

The arrow function could be considered a better practice since the parameters and arguments are explicit (more important if the method declaration is far away). bind could be considered more maintainable, as you don't need to touch it when adding/removing parameters. However, you can achieve the same with an arrow function and rest/spread syntax:

theirPromise((...args) => this.myHandler_(...args));

Now the only difference is bind being shorter, creating a function with correct .length, evaluating the this.myHandler_/this references immediately and some other peanuts.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • It's also important to note that `bind` effectively creates a copy of the function with its new scope — this can be good to use if you plan on reusing that function more than once – Nick Zuber Nov 29 '16 at 01:15
  • @NickZuber "with its new scope" --- what does it mean? – zerkms Nov 29 '16 at 01:16
  • @zerkms I was referring to the scope that was just bound to the function – Nick Zuber Nov 29 '16 at 01:17
  • @NickZuber It's called "context" or "receiver", and that's not a difference because you could share/reuse the arrow function just as well. – Bergi Nov 29 '16 at 01:18
  • @Bergi How would you be able to "reuse" an arrow function in this way? With binding, you can have `let newFun = oldFun.bind(this)` and then use `newFun` where ever you need, whereas with an arrow function you only bind the scope _as_ you execute the function — how can you "reuse that"? – Nick Zuber Nov 29 '16 at 01:20
  • 2
    @NickZuber `let newFun = () => oldFun.call(this); newFun(); newFun();` works just as well. Not sure what you mean by "*bind the scope as you execute the function*" - the closure over a scope is formed when the function is created, not when it's executed. – Bergi Nov 29 '16 at 01:26
  • Thanks for the answer. I like the spread operator use. I should have mentioned that a subjective answer was what I was expecting / looking for, or some kind of convention or style guide reference. – cyrus Nov 29 '16 at 02:14
  • 1
    @cyrus I don't know of any that detail this particular thing. In cases where the differences don't matter, I believe it comes down to the "*oh let's go for new shiny ES6 style everywhere*" vs "*let's keep it simple and stay with ES5 where easily possible*" fractions. Oh, and consistency is a big thing, so if you need arrow functions for some method callbacks you'll want to use them everywhere. – Bergi Nov 29 '16 at 02:22