Skip to main content

Function.prototype.apply

/**
* Custom implementation of Function.prototype.apply.
*
* Usage:
* fn.myApply(thisArg, argsArray)
*
* @param {unknown} thisArg
* @param {ArrayLike<unknown> | null | undefined} argsArray
* @returns {unknown}
*/
Function.prototype.myApply = function (thisArg, argsArray) {
if (typeof this !== 'function') {
throw new TypeError('myApply must be called on a function');
}

const context =
thisArg === null || thisArg === undefined ? globalThis : Object(thisArg);

const tempKey = Symbol('myApply');
context[tempKey] = this;

try {
if (argsArray === null || argsArray === undefined) {
return context[tempKey]();
}

// Support array-like input, not only real arrays.
const listObject = Object(argsArray);
const length = Number(listObject.length) >>> 0;
const args = new Array(length);

for (let i = 0; i < length; i++) {
args[i] = listObject[i];
}

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

/**
Example:

function greet(greeting, punctuation) {
return `${greeting}, ${this.name}${punctuation}`;
}

greet.myApply({ name: 'Ada' }, ['Hello', '!']);
// 'Hello, Ada!'
*/