Implement Function.prototype.call yourself
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
thisinsidefn. ...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
fnwiththisset tothisArg. - Forward
argsas the function's arguments and return its return value. - Work when
Function.prototype.call,applyandbindhave been replaced with throwing stubs. - Leave no extra own property behind on
thisArg, including symbol-keyed ones.
Notes
- The trick: assign
fnto a temporary property onthisArg, invoke it through the dot (thisArg[key](...args)— the dot setsthis), then delete the property in afinallyblock. - 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.
- 1.sets this on the call
- 2.forwards the arguments
- 3.passes no arguments when none are given
- 4.leaves the receiver untouched
- 5.does not rely on call, apply or bind
These assertions run in your browser the moment you hit Run. Pass all of them to claim the XP.
Discussion
Sign in to postNo comments yet. Be the first to say something.