Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding Function Type prototypes

I have come across an interesting behavior when playing around and trying to override Function prototype.

Let's assume we have overriden toString() like this:

const funcToString = Function.prototype.toString;
Function.prototype.toString = function() { 
    console.log("lol"); 
    return funcToString.call(this); 
}

Now, lets take this into action and see what happens:

(function foo(){}).toString(); // TypeError

TypeError: Function.prototype.toString requires that 'this' be a Function

By doing some reading, I've learned that this has something to do with how internally Function wraps it in a Proxy - and it being indistinguishable from it's target, results in a TypeError.

But now, we can try doing this:

function boo(){};
boo.toString(); // prints "lol", as we wanted

To add to all this, I've only observed this behavior in browser runtimes. In Node.js, everything goes well in both scenarios.

EDIT: Confirmed to work in REPL without any errors whatsoever.

Personally I fail to understand what the difference is / what exactly happens. Would be grateful if someone could shine some light on this.

like image 937
Kamil Solecki Avatar asked Apr 30 '26 12:04

Kamil Solecki


1 Answers

This is a problem of a missing semicolon:

Function.prototype.toString = function() { 
    …
}; /*
 ^ */
(function foo(){}).toString();

Otherwise it is interpreted as

Function.prototype.toString = function(){…}(function foo(){}).toString();

which calls the function expression that is supposed to override toString like an IIFE

… (function(){…}(function foo(){})) …

…in the global context, not on a function.

like image 150
Bergi Avatar answered May 02 '26 01:05

Bergi