1

This function computes f(g(...arg)) in JavaScript.

function compose(f,g){
   return function(...arg){
       return f.call(this, g.apply(this, args)};
   }
}

I know that the first argument to the methods call and apply is the invocation context. However, I am not sure what's the significance of the this keyword in both call and apply methods above. It's clearer to me when the invocation context is an object like {x:1}, and then we use could use this.x to access the property x, but I am not clear on the use of this in the above context. Why do we use this like that in the above code?

EDIT: the functions are called with these functions:

const sum = (x, y) => x + y;
const square = x => x * x;
compose(square, sum)(2, 3);
VLAZ
  • 18,437
  • 8
  • 35
  • 54
BlackMath
  • 482
  • 3
  • 10
  • 1
    In your specific case, it refers to the anonymous function itself. You can also look at the answers to this question : https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work – Seblor Mar 29 '21 at 16:11
  • 1
    @Seblor it doesn't? As always, it depends on how it's called. – VLAZ Mar 29 '21 at 16:11
  • Since the anonymous function doesn't have any properties, it would be pretty pointless if it *was* the value of `this` (which, as VLAZ points out, it isn't). – Quentin Mar 29 '21 at 16:13
  • @VLAZ I fail to see how it could not refer to the anonymous function with this snippet. I would genuinely be interested to see a case where it would not be the case. – Seblor Mar 29 '21 at 16:14
  • 1
    @Seblor `this` pretty much never refers *to a function*. Look at the link you posted. It depends on *how the function is called*. The vast majority of time it's something like `obj.foo()` which calls `foo` with `this = obj`. Calling *just* `foo` will not set a `this` context (the results vary between strict and non-strict mode). Explicitly supplying a `this` parameter through `.call`/`.apply` is the only way to make it refer to a function but that's also seldom done. – VLAZ Mar 29 '21 at 16:16
  • @VLAZ — Well. Since functions are objects you can also have a function as a property of another function and then: `firstFunction.otherFunction()` but that's also seldom done. (I think jQuery is the only example I can think of and it overloads absolutely everything in ways I wouldn't recommend). – Quentin Mar 29 '21 at 16:19
  • @VLAZ I added how and where the function is called. What's the value of `this` in this case? The invocation context I think is the global object, right? If yes, what is the significance of using `this` in the above code? In other words, what would happen if I put `null` in its place? It's (`this`) not being used in the functions, right? – BlackMath Mar 29 '21 at 16:19
  • @VLAZ ah, right. I made a wrong assumption in my mind at some point. Thanks :) – Seblor Mar 29 '21 at 16:22

1 Answers1

1

This is because we want to preserve the original calling value of this and forward it to all composed functions.

This doesn't matter if we compose together functions that do not use this as is your example:

const sum = (x, y) => x + y;
const square = x => x * x;
compose(square, sum)(2, 3);

Here, this is irrelevant.

However, the composition is generic and should apply to any pair of functions. We could use this, in which case it's good to preserve how they work in case it matters:

function compose(f, g){
   return function(...args){
       return f.call(this, g.apply(this, args));
   }
}

function introduce(greeting) {
  return `${greeting}! My name is ${this.name}.`;
}

function addRandomFact(str) {
  return `${str} I like ${this.hobby}.`;
}

const person1 = {
  name: "Alice",
  hobby: "pancakes",
  introduce: introduce,
}

console.log(person1.introduce("Hello"));

const person2 = {
  name: "Bob",
  hobby: "turtles",
  introduce: compose(addRandomFact, introduce)
}

console.log(person2.introduce("Hola"));
VLAZ
  • 18,437
  • 8
  • 35
  • 54