The ECMAScript 2015 official spec on Function.prototype
says (ECMA-262 6th Ed. §19.2.3.6):
[The
Symbol.hasInstance
property] is non-writable and non-configurable to prevent tampering that could be used to globally expose the target function of a bound function.
Now, even non-writable and non-configurable properties of the prototype can be overwritten with Object.defineProperty
and indeed if you try to overwrite Symbol.hasInstance
to always return true then it will do so.
I don't understand the quote though.
Presumably the scenario where the global function could be exposed is in the case of a bound function when you overwrite the target's Symbol.hasInstance
to return true. Naturally it would return false because the target swaps its prototype onto the bound function, and therefore the bound function is not an instance of the target. Also, to my best understanding I believe the reason it would end up on the global scope is because a bound function has no prototype and therefore cannot physically be an instance of the target function, so if you force it as an instance then the target's prototype is forced on the non-existent bound prototype and it ends up failing and placing the target's this
on the global scope. However, even when I set it to return true I still cannot get it to expose the target globally.
Note, this is something I am trying to do to better understand the inner workings of JavaScript. In practical application I wouldn't want to expose the target globally.
I have tried hours and hours of fiddling with a range of code snippets of bound functions and Symbol.hasInstance
returning true but to no avail. I cannot get it to expose the target's functions and data globally. If anyone understands this better it would really be greatly appreciated. I've hit a brick wall.
What the quoted passage refers to is that you cannot do:
// A malicious library loads here and overrides the function.
(function(){
Object.defineProperty(Function.prototype, Symbol.hasInstance, {
value: function(instance){
const context = this;
// Here, `this === SomeClass`
},
});
}();
// Some library loads here.
(function(){
function SomeClass(){}
const BoundClass = SomeClass.bind(null);
var tmp = {} instanceof BoundClass;
})();
So in this example, if the property were configurable: true
, a malicious library would be able to access SomeClass
, which would otherwise have been an entirely private and scoped within an IIFE.