Dynamically calling a method from a class in ES6

How can a method be called dynamically from a class in ES6?

In ES5 and below, I can do it with the following. JSFiddle example

var App = function() {

    var that = this;

    this.init = function() {
        var elements = document.getElementsByClassName('call-method');

        for(var i = 0; i < elements.length; i++) {
            elements[i].addEventListener('click', function() {
                that['method' + this.dataset.method](this);
            });
        }
    };

    this.methodOne = function(element) {
        console.log(element.innerText);
    };

    this.methodTwo = function(element) {
        console.log(element.innerText);
    };

};

(function() {
    var app = new App();

    app.init();
}());

      

When I try to do the same in ES6, I get an error Uncaught TypeError: not a function

. Is this possible in ES6 or am I doing something wrong here? JSFiddle example

'use strict';

class App {

    constructor() {
        var elements = document.getElementsByClassName('call-method');

        for(var i = 0; i < elements.length; i++) {
            elements[i].addEventListener('click', function() {
                this.constructor['method' + this.dataset.method](this); // Uncaught TypeError: not a function
                App['method' + this.dataset.method](this); // Uncaught TypeError: not a function
            });
        }
    }

    methodOne(element) {
        console.log(element.innerText);
    }

    methodTwo(element) {
        console.log(element.innerText);
    }

}

(function() {
    new App();
}());

      

+3


source to share


2 answers


I think you don't understand how ES6 classes work. Your first strategy will not work because this.constructor is a method and not a reference to any constructor class. The second will not work because it will only refer to a static method.

Instead

constructor() {
    var elements = document.getElementsByClassName('call-method');

    for(var i = 0; i < elements.length; i++) {
        elements[i].addEventListener('click', (e) => {
            this['method' + e.target.dataset.method](e);
        });
    }
}

      



Also arrow functions will be the best way to bind an event.

Edit: Updated your fiddle to show it in action - http://jsfiddle.net/dqk8n3xk/3/

+3


source


You can do the following:

'use strict';

class App {

    constructor() {
        var that = this;

        var elements = document.getElementsByClassName('call-method');

        for(var i = 0; i < elements.length; i++) {
            elements[i].addEventListener('click', function() {
                that['method' + this.dataset.method](this);
            });
        }
    }

    methodOne(element) {
        console.log(element.innerText);
    }

    methodTwo(element) {
        console.log(element.innerText);
    }

}

(function() {
    new App();
}());

      



as shown in this jsfiddle

+2


source







All Articles