0

How can I use a prototype's method with this referencing to the prototype in a higher order function like reduce?

Example code:

function A() {

  this.names = ["John", "Jane", "Doe"];

  this.printMergedNamesByIndexes = function() {
    const indicies = [0,1,2]
    console.log(indicies.reduce(this.mergeNames, ""))
  };

  this.mergeNames = function(accumulator, index) {
    return accumulator + this.names[index] + ", "
  };
}

const a = new A()
a.printMergedNamesByIndexes()

I'd like to pass the mergeNames method of the prototype to the reducefunction, but in that case the this value in the mergeNamesmethod does not reference to the prototype itself. So I got an error:

TypeError: undefined is not an object (evaluating 'this.names[index]')

I found this post: Using prototype functions in higher order functions in javascript , but the bindmethod gave me a similar error like above, except it was complaining about the nonexistence of the bind method.

danieltmbr
  • 1,022
  • 12
  • 20
  • `mergeNames` is not a prototype method (I don't see any `prototype` in your code) but an instance method, although it doesn't make a difference: you should indeed use `bind`. Please show us your attempt of using it. – Bergi Oct 14 '17 at 19:49

1 Answers1

0

The solution was using lambda/arrow function.

Arrow functions MDN web docs

An arrow function does not create its own this; the this value of the enclosing execution context is used.

That means passing an arrow function to a higher order function will catch the this value of the current scope. In this case it means it catches the prototype object as this so we can use its methods inside the arrow function.

function A() {

  this.names = ["John", "Jane", "Doe"];

  this.printMergedNamesByIndexes = function() {
    const indicies = [0,1,2]
    console.log(indicies.reduce(this.merge, ""))
  };

  // Arrow function
  this.merge = (accumulator, index) => {
    // "this" referencing to the prototype
    return accumulator + this.names[index] + ", "
  };
}

const a = new A()
a.printMergedNamesByIndexes()
danieltmbr
  • 1,022
  • 12
  • 20
  • 2
    Or you could do `indicies.reduce(this.merge.bind(this), "")` – dfsq Oct 14 '17 at 17:47
  • ... or stop using `this` and `prototype` completely. – PeterMader Oct 14 '17 at 17:48
  • @PeterMader Is it a bad practice using prototypes? I don't use often Js so could you explain it? – danieltmbr Oct 14 '17 at 17:55
  • 1
    Well, I mostly use JavaScript to do functional programming, rather than dealing with object oriented programming and inheritance. But there are ways to get around the prototype (for example, class free programming; more info [here](https://dannyfritz.wordpress.com/2014/10/11/class-free-object-oriented-programming/) and [here](https://stackoverflow.com/questions/27595749/douglas-crockford-on-class-free-oop-in-javascript)). But that's a little eccentric, most people stick with prototypal inheritance (or fake class-based inheritance, because they don't understand the prototype). – PeterMader Oct 14 '17 at 18:00
  • @PeterMader You might want to notice that he already is not using `prototype` at all – Bergi Oct 14 '17 at 19:50
  • @Bergi but he's using `this`, which causes the problems class free programming aims to solve. – PeterMader Oct 14 '17 at 20:01