In what cases, we want to use apply with this?

I understand how this works but cant understand why we want to use apply with "this" keyword as in a example below:

function curry(func) {
    return function curried(...args) {

        if (args.length >= func.length) {
            return func.apply(this, args)
        } else {
            return curried.bind(this, ...args)
        }
    }
}

Here bind and apply use "this" as a first argument, but what is the purpose if we can just do func(args) since this points to same lexical environment of a function. I can see some benefits with it with arrow functions but here I have named functions. There is no difference or I am missing something?


The reason for using apply is to keep the same the value of this. Calling func(args) would result in this being the window object (in non-strict mode) or undefined (in strict mode).

Here's an example that breaks if you call func(args):

function curry(func) {
  return function curried(...args) {
    if (args.length >= func.length) {
      return func(args);
    } else {
      return curried.bind(this, ...args);
    }
  };
}

const example = {
  multiplier: 5,
  calculate: function (a, b) {
    return (a + b) * this.multiplier;
  },
};
example.curriedVersion = curry(example.calculate);

// Because of the way these are being called, `this` should be `example`
console.log(example.calculate(1, 2));
// But here it's not, causing unexpected results
console.log(example.curriedVersion(1)(2));

But it works if you do apply(this, args):

function curry(func) {
  return function curried(...args) {
    if (args.length >= func.length) {
      return func.apply(this, args);
    } else {
      return curried.bind(this, ...args);
    }
  };
}

const example = {
  multiplier: 5,
  calculate: function (a, b) {
    return (a + b) * this.multiplier;
  },
};
example.curriedVersion = curry(example.calculate);

// Because of the way these are being called, `this` should be `example`
console.log(example.calculate(1, 2));
console.log(example.curriedVersion(1)(2));