preface

Using the ES class, is it more efficient to use the arrow function or to bind the function to the context using the bind function from the constructor function? In Demystifying Memory Usage using ES6 React Classes, the following conclusions are presented.

Above is the way to create a class using the arrow function in class. The author calls this class properties. As you can see, each instance of a handler method defined in a class using the arrow function has a separate handler function. When the number of instances is small, this approach does not cause a large amount of memory waste, but when the number of instances is in the tens of thousands, this approach becomes inefficient in terms of memory usage. Wouldn’t it be nice to be able to share handlers on a class?

Using constructor function bindings can reduce memory usage even more effectively. By binding the function inside the constructor function, the code looks like this:

class MyClass extends Component {
  constructor() {
    super();
    this.state = { clicks: 0 };
    this.handler = this.handler.bind(this);
  }
  handler() {
    this.setState(({ clicks }) => ({ clicks: clicks + 1 }));
  }
  render() {
    const { clicks } = this.state;
    return(
      <button onClick={this.handler}>
        {`You've clicked me ${clicks} times`}  ); }}Copy the code

Each instance while inside have a handler method (this handler, not MyClass. Prototype. Handler), but each instance of this. A handler is actually Shared MyClass. Prototype. The handler function body.

So how does this work? Bind function MDN Polyfill implementation:

if(! Function.prototype.bind) { Function.prototype.bind =function(oThis) {//oThis stands for object thisif(typeof this ! = ='function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this, //
        fNOP    = function() {},
        fBound  = function() {
          returnfToBind.apply(this instanceof fNOP ? This: oThis, / / get a call (fBound) ginseng. Bind returns the function into the participation is often so pass aArgs. Concat (Array) prototype. Slice. The call (the arguments))); }; // Maintain prototype relationshipsif (this.prototype) {
      // Function.prototype doesn't have a prototype property fNOP.prototype = this.prototype; } fBound.prototype = new fNOP(); return fBound; }; }Copy the code

Can be seen from the above code, we use the bind in the constructor, after binding function actually returns a function (fBound), returned by the function of the body of the function and binding (MyClass. Prototype. Handler) of the body of the function is different. The returned function simply calls the function to be bound inside the function body. In other words, by using the bind binding in the constructor function, the generated instances, there will be a separate fBound, function body relative to the binding function of smaller, and in each instance fBound Shared with binding function is invoked during (MyClass. Prototype. Handler)

conclusion

As you can see by comparison, each instance can effectively share the function body using the constructor bind method, thus using memory more efficiently. However, when there are many functions to bind, this method is relatively dull and boring. So, I think it’s faster to use the arrow function if you know that there are not many instances and the function body is not large.