Because javascript is prototypical, it's very easy to hook functions to run your own code. For example, you might want to count how many times a function is called (at least, this is why I needed it) or print it out when it's called.
All you have to do is just reassign it to a different variable, preferably global.
b = Math.random; // we make a reference to a so we don't called a recursively in its body
a = function()
{
console.log("hook!") // the hook code goes here
return b(); // return b() so we don't blow up the call stack
}
Math.random = a; // and now Math.random looks at a, which calls b and "hook!"
and now, when you call Math.random()
, you should see "hook!"
in the console:
/**
* Converts an array of arrays, i.e.
* [ [...], [...], ... ]
* to a csv string.
*/
Array.toCSVString = (array) =>
{
for(let elem of array)
{
//Run through each element of the array
//..
//If the iterated element is a string, then wrap this
//whole string with quotes
for(let i = 0; i < elem.length; i++)
if(typeof(elem[i]) == "string")
elem[i] = elem[i].replace(/(.+\,.+)/, "\"$1\"");
}
//Then just join each column with "," and each row up with "\n".
return array.map((x) => x.join(",")).join("\n");
}
/**
* Converts an array of objects, i.e.
* [ {...}, {...}, ...]
* to a csv string. At the moment this can only
* handle top-level object properties (at depth 0).
*/
Array.toCSV = (array) =>
{
//Is this an array?
assert(Array.isArray(array));
//Is this array not empty?
assert(array.length > 0);
//Get the headers of the first element -- this will be the
//same throughout
let headers = Object.keys(array[0]);
//Map all data to its actual values
let data = array.map((x) => Object.values(x));
//And build an array of arrays
let final_data = [ headers, ...data ];
//Convert the array of arrays to a csv string
return Array.toCSVString(final_data);
}