How do I wrap a function in Javascript?
Personally instead of polluting builtin objects I would go with a decorator technique:
var makeSafe = function(fn){ return function(){ try{ return fn.apply(this, arguments); }catch(ex){ ErrorHandler.Exception(ex); } };};
You can use it like that:
function fnOriginal(a){ console.log(1/a);};var fn2 = makeSafe(fnOriginal);fn2(1);fn2(0);fn2("abracadabra!");var obj = { method1: function(x){ /* do something */ }, method2: function(x){ /* do something */ }};obj.safeMethod1 = makeSafe(obj.method1);obj.method1(42); // the original methodobj.safeMethod1(42); // the "safe" method// let's override a method completelyobj.method2 = makeSafe(obj.method2);
But if you do feel like modifying prototypes, you can write it like that:
Function.prototype.TryCatchWrap = function(){ var fn = this; // because we call it on the function itself // let's copy the rest from makeSafe() return function(){ try{ return fn.apply(this, arguments); }catch(ex){ ErrorHandler.Exception(ex); } };};
Obvious improvement will be to parameterize makeSafe() so you can specify what function to call in the catch block.
2017 answer: just use ES6. Given the following demo function:
function doThing(){ console.log(...arguments)}
You can make your own wrapper function without needing external libraries:
function wrap(someFunction){ function wrappedFunction(){ var newArguments = [...arguments] newArguments.push('SECRET EXTRA ARG ADDED BY WRAPPER!') console.log(`You're about to run a function with these arguments: \n ${newArguments}`) return someFunction(...newArguments) } return wrappedFunction}
In use:
doThing('one', 'two', 'three')
Works as normal.
But using the new wrapped function:
const wrappedDoThing = wrap(doThing)wrappedDoThing('one', 'two', 'three')
Returns:
one two three SECRET EXTRA ARG ADDED BY WRAPPER!
2016 answer: use the wrap
module:
In the example below I'm wrapping process.exit()
, but this works happily with any other function (including browser JS too).
var wrap = require('lodash.wrap');var log = console.log.bind(console)var RESTART_FLUSH_DELAY = 3 * 1000process.exit = wrap(process.exit, function(originalFunction) { log('Waiting', RESTART_FLUSH_DELAY, 'for buffers to flush before restarting') setTimeout(originalFunction, RESTART_FLUSH_DELAY)});process.exit(1);
Object.extend(Function.prototype, {Object.extend in the Google Chrome Console gives me 'undefined'Well here's some working example:
Boolean.prototype.XOR =// ^- Note that it's a captial 'B' and so// you'll work on the Class and not the >b<oolean object function( bool2 ) { var bool1 = this.valueOf(); // 'this' refers to the actual object - and not to 'XOR' return (bool1 == true && bool2 == false) || (bool1 == false && bool2 == true); } alert ( "true.XOR( false ) => " true.XOR( false ) );
so instead ofObject.extend(Function.prototype, {...})Do it like:Function.prototype.extend = {}