Sat 5 Apr 2008
Here’s a fun bit of JavaScript inspired by Yehuda Katz’s jspec. It lets you call a function with a particular scope, making it ideal for calling functions that depend on a particular scope, but for whatever reason you don’t want to set up that scope statically.
function callWithScope(fn, context, scope) {
var fn_body = fn.toString().match(/^[^\{]*\{((.*\n*)*)\}/m)[1];
fn = new Function('__scope__', 'with(__scope__){\n' + fn_body + '\n}');
return fn.call(context, scope);
}
How might this be used? When writing a JavaScript spec, allowing the describe callback function to call it.
describe("callWithScope", function() {
it("should not retain the original function scope", function() {
...
})
})
Notice that it doesn’t appear to come from anywhere. When the callback passed to describe is given to callWithScope, the call might look something like this:
callWithScope(callback, this, {it: function(name, body) { ... }})
The describe callback function is turned into a string and turned into a new function of one argument, the scope. It makes it look something like this, though this isn’t entirely accurate:
describe("callWithScope", function(__scope__) {
with(__scope__) {
it("should not retain the original function scope", function() {
...
})
}
})
I’m using this in one project to call functions defined in some external scripts that expect certain objects and functions to be available. Also, since I can pass in my custom scope, I don’t have to do the work of ensuring that every function that needs that scope is declared within it. This allows me to abstract out a lot of shared code.
I’m sure there are a lot of uses for this I haven’t thought of. What’s yours?