For a project I will talk later on, I need to hook the function document.createElement
. The code I wanted to write was:
var original = document.createElement; document.createElement = function (tag) { // Do something return original(tag); }; |
Problem
However, there's a silly Javascript exception triggered if you try to take a reference of the function
var createElement = document.createElement; createElement('div'); // TypeError: Illegal Invocation |
Naive Solution
Since it looks like we cannot use anything else but document.createElement
to execute the function, I decided to restore the original document.createElement
within the hook function. It is verbose but works.
var original = document.createElement; var hook = function (tag) { document.createElement = original; // Do something var el = document.createElement(tag); document.createElement = hook; return el; }; document.createElement = hook; |
Why?
But then, I asked myself, how did they implement a function that could only be called with document.createElement
form. Then I remembered that this calling convention sets this
to be document
. So they must be doing a check like this:
document.createElement = function () { if (this !== document) { throw new TypeError('Illegal Invocation'); } // ... } |
Solution
Now that we know that they check for this === document
, we can use .call
to force it 🙂
var original = document.createElement; document.createElement = function (tag) { // Do something return original.call(document, tag); }; |