krl
krl

Reputation: 5296

Passing method of a constructed object to a function in JavaScript

The code below would work in case of regular functions but it doesn't work in case of object methods.

I'm getting the following error:

  return this.anotherService.get1(start, end);
              ^
  TypeError: Cannot read property 'anotherService' of undefined

How do I rewrite the code to make getTransactions a general helper function executing different methods passed as arguments?

class Service {
  constructor(arg1) {
    this.anotherService= new AnotherService(arg1);
  }

  getMethod1(start, end) {
    return this.anotherService.get1(start, end);
  }

  getMethod2(start, end) {
    return this.anotherService.get2(start, end);
  }
} 

function getTransaction1(arg1, arg2, arg3) {
  let service = new Service(arg1);
  getTransactions(arg2, arg3, service.getMethod1);
};

function getTransaction2(arg1, arg2, arg3) {
  let service = new Service(arg1);
  getTransactions(arg2, arg3, service.getMethod2);
};

function getTransactions(arg2, arg3, func) {
  let start = ......;
  let end = ........;
  func(start, end).then(data => {
    res.json(data);
  }).catch(console.log);
};

Upvotes: 0

Views: 30

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074118

You can use Function#bind to handle that:

function getTransaction1(arg1, arg2, arg3) {
  let service = new Service(arg1);
  getTransactions(arg2, arg3, service.getMethod1.bind(service));
  // -------------------------------------------^^^^^^^^^^^^^^
}

function getTransaction2(arg1, arg2, arg3) {
  let service = new Service(arg1);
  getTransactions(arg2, arg3, service.getMethod2.bind(service));
  // -------------------------------------------^^^^^^^^^^^^^^
}

Function#bind returns a new function that, when called, will call the original with this set to be the object you pass to bind. (You can also pass additional arguments to bind, but that's not relevant here.)


Or, of course, you can create getMethod1 and getMethod2 within your constructor using fat arrow functions, which get a lexical this binding:

class Service {
  constructor(arg1) {
    this.anotherService= new AnotherService(arg1);
    this.getMethod1 = (start, end) => {
        return this.anotherService.get1(start, end);
    };
    this.getMethod2 = (start, end) => {
        return this.anotherService.get2(start, end);
    };
  }
} 

...in which case you don't have to change getTransaction1 and getTransaction2 at all.


Side note: Function declarations (what you're using with getTransaction1 and getTransaction2) aren't statements, and so they aren't terminated with semicolons.

Upvotes: 1

Related Questions