Given the following snippet of javascript in a scope:
var x = 10;
function sayx() {
alert(x);
}
sayx();
You would of course expect a message box printing '10', you could do multiple function nesting to interact with how 'x' is determined, because when resolving what x is the environment walks up the scope chain.
You can even do a level of 'recompilation' with eval to inject new scopes at runtime.. for example:
var x = 10;
function sayx() {
alert(x);
}
function wrap(f) {
return eval('(function() { var x = 20;(' + f + ')(); })');
}
wrap(sayx)();
This works because the function will have its toString function called which will return the 'original' source.. thus we essentially create a wrapped version of the function that has a new scope that overrides x.. the result will be an alert box that prints '20' and not '10'.
However, on the surface this could appear to work but the scope chain is broken, the next item in the chain is no longer the same because the function 'f' is now defined at a different location.. even worse is that the scope chain it has inherited could contain many references that the calling function shouldn't have access to.
So, is there a more supported, workable way to inject a scope item? something like:
function withScope(f, scope) { ??? }
---
var x = 10, y = 10;
function dothemath() {
alert(x + y);
}
var haxthemath = withScope(dothemath, { x: 9000 });
haxthemath(); // 9010 not 20
I'm guessing the answer is 'no', some may argue there are 'security' issues with such scope injection, but considering you can do the trick anyway (albeit severely broken) I don't think it is..
The benefits of this would be that you can essentially fake your own pseudo variables.
Thanks in advance.
Edit, just the clarify a little, imagine I wanted to 'withScope' a function that had the following scope chain:
Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }
I would like to be able to get a function back that effectively had the same chain + a scope I provide.. ie:
withScope(somefunc, { foo: 'bar' })
Would give me
Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }
Ext scope - { foo = 'bar' }
All prior standing variables would be found because my extended scope doesn't say anything about them.
If you are refering by scope to the local variables in the function and/or the closure, I think the answer is no.
You can change the scope of the this keyword by using functionName.call(scope, arg1, ...) or functionName.apply(scope, [arg1, ...]); This could be used together with prototypes to create similar chains as you describe - if something isn't found in the object's own properties, it's looked up in its prototype. If the property is not there, the next prototype in the chain is used and so on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With