Created
July 24, 2010 00:10
-
-
Save ELLIOTTCABLE/488236 to your computer and use it in GitHub Desktop.
instanceEval for JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var instanceEval, origArgs | |
// This approach, by Tim Caswell (creationix) coerces the input function into a string, ensuring said function | |
// will be called with `instanceEval()`’s `this`, and then `with()`s that input function against `this` as well. | |
// This exposes the keys attached to the `this` you call `instanceEval()` on as variables within the input | |
// function. | |
instanceEval = function (input) { | |
if (typeof(input) === "function") input = "("+input+").call(this)"; return eval("with(this){"+input+"}") } | |
;(function(){ var first = "Bob", middle = "Johnathan", last = "Smith" | |
// ReferenceError: middle is not defined | |
try { instanceEval.call({first:"Tim", last:"Caswell"}, function(){ console.log(first+" "+middle+" "+last) }) } | |
catch (error) { console.error((error.type === "not_defined"?"ReferenceError":error.type)+": "+error.message) } | |
})() | |
// I take a different approach (also possibly faster at runtime of the function): I avoid `with()`, and instead | |
// serialize the keys from the object being `instanceEval()`ed upon into a series of variable names, and then | |
// pass those in as arguments to an invisible, anonymous function. | |
origArgs = "__origArgs", | |
instanceEval = function (input) { var that, variables, values | |
if (typeof(input) === "function") input = "("+input+").apply(this, "+origArgs+")" | |
values = (variables = Object.getOwnPropertyNames(that = this)).map(function(variable){return that[variable]}) | |
variables[variables.length] = origArgs; values[values.length] = Array.prototype.slice.call(arguments, 1) | |
return (eval("(function("+variables.join(",")+"){return ("+input+")})").apply(this, values)) } | |
;(function(){ var first = "Bob", middle = "Johnathan", last = "Smith" | |
// ReferenceError: middle is not defined | |
instanceEval.call({first:"Tim", last:"Caswell"}, function(){ console.log(first+" "+middle+" "+last) }) | |
catch (error) { console.error((error.type === "not_defined"?"ReferenceError":error.type)+": "+error.message) } | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment