AniUI Academy

Implement Function.prototype.call yourself

mediumFunctions & Closures+250 XPPractice

this in JavaScript is not a property of a function, it is a property of the *call*: whatever sits to the left of the dot becomes the receiver. Once that clicks, invoking a function with an arbitrary receiver needs no special machinery at all — you can put the function on the object temporarily and call it through the object.

Implement myCall(fn, thisArg, ...args). It invokes fn with this set to thisArg and with args as its arguments, and returns whatever fn returns. You may assume thisArg is always an object. Your implementation must not use Function.prototype.call, apply or bind: one of the tests replaces all three with functions that throw before calling myCall. It must also leave thisArg exactly as it found it — after myCall returns, thisArg has no extra own property, neither a string-keyed one nor a symbol-keyed one.

Arguments

fnFunction
The function to invoke.
thisArgobject
The receiver — the value of this inside fn.
...argsany[]
The arguments to pass to fn.

Returns

any — Whatever fn returns when invoked with the given receiver and arguments.

Examples

function whoAmI() { return this.name; }

myCall(whoAmI, { name: "Ada" });        // "Ada"
myCall(whoAmI.bind({ name: "x" }), { name: "y" }); // "x" (bind wins)
function greet(greeting, punct) {
  return greeting + ", " + this.name + punct;
}

myCall(greet, { name: "Ada" }, "Hi", "!"); // "Hi, Ada!"

What it has to do

  • Invoke fn with this set to thisArg.
  • Forward args as the function's arguments and return its return value.
  • Work when Function.prototype.call, apply and bind have been replaced with throwing stubs.
  • Leave no extra own property behind on thisArg, including symbol-keyed ones.

Notes

  • The trick: assign fn to a temporary property on thisArg, invoke it through the dot (thisArg[key](...args) — the dot sets this), then delete the property in a finally block.
  • Use Symbol("myCall") as the key so you never collide with a real property, and so a symbol-key enumeration check cannot see your leftovers.

Stuck? The javascript course covers everything this challenge needs.

Try it yourself
Loading playground...
5 tests · +250 XP

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.