So, I want to do something like this:
var a = 'a';
var dummy = function() {
// Print out var 'a', from the scope above
console.log('Dummy a: ' + a);
// Print out 'b', from the 'pelled' scope
console.log('Dummy b: ' + b);
}
(function() {
var b = 'otherscope';
// I know apply won't work, I also don't want to merge scopes
dummy.apply(this);
// I want something like this:
dummypel(this, [], {b: 'injected!'});
})();
But that won't work.
I don't actually want a function to be able to reach 2 scopes, I DO want to be able to set the 'b' variable used inside the dummy function from the outside.
So, I want to do something like this:
var a = 'a';
var dummy = function() {
// Print out var 'a', from the scope above
console.log('Dummy a: ' + a);
// Print out 'b', from the 'pelled' scope
console.log('Dummy b: ' + b);
}
(function() {
var b = 'otherscope';
// I know apply won't work, I also don't want to merge scopes
dummy.apply(this);
// I want something like this:
dummy.pel(this, [], {b: 'injected!'});
})();
But that won't work.
I don't actually want a function to be able to reach 2 scopes, I DO want to be able to set the 'b' variable used inside the dummy function from the outside.
Share Improve this question asked Mar 21, 2013 at 19:14 Jelle De LoeckerJelle De Loecker 22k29 gold badges104 silver badges146 bronze badges 3- Whats the application for doing this? There might be other techniques people could suggest – user2033671 Commented Mar 21, 2013 at 19:29
- 1 Maybe this is a (plex) workaround: stackoverflow./questions/10060857/… – bfavaretto Commented Mar 21, 2013 at 19:30
- I mainly want to see if it's possible. Well, I actually want to use it in a node.js MVC. I don't like that every action has set arguments, this would have been nicer. @bfavaretto has shown me a nice workaround, though I fear using eval() will be too much of a performance hit :) – Jelle De Loecker Commented Mar 21, 2013 at 19:38
4 Answers
Reset to default 6You can make b
a parameter for the function, or a global variable.
var a = 'a';
var dummy = function(b) {
...
}
or
var a = 'a';
var b;
var dummy = function() {
...
}
The first allows you to choose when the dummy function has access to the variable, the second allows it to be accessed everywhere.
So, I found a little faster way to do such a thing:
var C = function(ctx, funcBody){
var newBody = [];
for(var k in ctx){
var i = "var "+k + " = ctx['"+k+"'];";
newBody.push(i);
}
var res = "return function(t){ " +funcBody+ " }";
newBody.push(res);
var F = new Function("ctx", newBody.join('\n'));
return F(ctx);
}
var newFunction = C({"foo":10, "bar":100}, "return foo+bar*t")
newFunction(50);
Use this:
Function.prototype.applyVars = function(scope, params, scope_variables) {
if (scope_variables) {
var variable, defVars = [];
for (variable in scope_variables) {
if (scope_variables.hasOwnProperty(variable)) {
defVars.push(variable + '=scope_variables["' + variable + '"]');
}
}
eval('var ' + defVars.join(',') + ';');
return eval('(' + this + ').apply(scope, params);');
}
return this.apply(scope, params);
}
// Example
function foo(p1) {
document.write('Variable [p1]: ', p1);
document.write('<br />');
document.write('Variable [x]: ', x);
document.write('<br />');
document.write('Variable [y]: ', y);
}
foo.applyVars(this, ['param X'], { x: "1'2\"3", y: false });
Or this:
function callWithVars(fn, scope, params, scope_variables) {
if (scope_variables) {
var variable, defVars = [];
for (variable in scope_variables) {
if (scope_variables.hasOwnProperty(variable)) {
defVars.push(variable + '=scope_variables["' + variable + '"]');
}
}
eval('var ' + defVars.join(',') + ';');
return eval('(' + fn + ').apply(scope, params);');
}
return fn.apply(scope, params);
}
// Example
function foo(p1) {
document.write('Variable [p1]: ', p1);
document.write('<br />');
document.write('Variable [x]: ', x);
document.write('<br />');
document.write('Variable [y]: ', y);
}
callWithVars(foo, this, ['param X'], { x: "1'2\"3", y: false });
the @vasiliy's solution extended to inject any function
function injectScope(ctx, func) {
var newBody = [];
for (var k in ctx) {
var i = " var " + k + " = ctx['" + k + "'];";
newBody.push(i);
}
let res = (func + '').replace(/^(.*?)\)\s*{(.*)$/gms, `return(\n$1){\n${newBody.join('\n')}\n$2)`);
// console.log(res)
let F = new Function("ctx", res);
return F(ctx);
}
function sum(t) {
return foo + bar * t
}
var injectedSum = injectScope({ "foo": 10, "bar": 100 }, sum)
// console.log(injectedSum+'')
console.log(injectedSum(50));