Q13: Implement a polyfill for Function.prototype.apply().

Difficulty:IntermediateTopic:Function Methods

Answer

The apply() method invokes a function immediately with a specified this value and arguments supplied as an array or array-like object.

Function.prototype.myApply = function (thisArg, argsArray) {
  if (typeof this !== "function") {
    throw new TypeError("myApply must be called on a function");
  }

  const fn = this;
  const context = thisArg == null ? globalThis : Object(thisArg);
  const key = Symbol("fn");
  const args = argsArray == null ? [] : Array.from(argsArray);

  context[key] = fn;

  try {
    return context[key](...args);
  } finally {
    delete context[key];
  }
};

function add(a, b, c) {
  return this.base + a + b + c;
}

console.log(add.myApply({ base: 10 }, [1, 2, 3]));
// 16

Explanation

The implementation follows the same temporary-property technique as the call() polyfill. The difference is that apply() accepts a single argument collection instead of separate arguments.

Array.from() supports common array-like objects and iterables. Native apply() has specific behavior for its arguments list and does not simply call Array.from() on every supplied value, so this is an interview-oriented approximation.

Key Takeaways
  • Apply invokes the function immediately with arguments from an array-like collection.
  • Call and apply differ mainly in how their arguments are supplied.