Is this scoping possible in javascript?
-
24-09-2019 - |
Question
I am working on a javascript framework. I have several independent scripts that look like this:
core.modules.example_module = function(sandbox){
console.log('wot from constructor ==', wot);
return{
init : function(){
console.log('wot from init ==', wot);
}
};
};
this function is called from another external script. I am trying to pass variables in to this function so that they can be accessed without using the this keyword.
The above example will error out saying wot is undefined.
If i wrap the function in an anonymous function and declare the variables there I get the expected desired results
(function(){
var wot = 'omg';
core.modules.example_module = function(sandbox){
console.log('wot from creator ==', wot);
return{
init : function(){
console.log('wot from init ==', wot);
}
};
};
})();
What i am trying to do is declare the variables further up the scope chain so they can be accessed in the module without using the this keyword like the second example. I don't believe this is possible as it looks like the functions execution scope is sealed on declaration of the function.
update
To clarify where I am trying to define wot. In a separate javascript file I have an object that calls a register module function like this
core = function(){
var module_data = Array();
return{
registerModule(){
var wot = "this is the wot value";
module_data['example_module'] = core.modules.example_module();
}
};
};
Solution
What you're looking for is called "dynamic scoping", where bindings are resolved by searching the current call-chain. It's not too common outside of the Lisp family (Perl supports it, via the local
keyword). Dynamic scoping is not supported in JS, which uses lexical scoping.
OTHER TIPS
Consider this example, using your code
var core = {}; // define an object literal
core.modules = {}; // define modules property as an object
var wot= 'Muhahaha!';
core.modules.example_module = function(sandbox){
console.log('wot from creator ==', wot);
return {
init: function() {
console.log('wot from init ==', wot);
}
}
}
// logs wot from creator == Muhahaha! to the console
var anObject = core.modules.example_module();
// logs wot from init == Muhahaha! to the console
anObject.init();
So long as wot
is defined somewhere in the scope chain for core.modules.example_module
at the point at which it is executed, this will work as expected.
Slightly off topic, but you've touched upon the scope of functions. Functions have lexical scope, that is they create their scope at the point at which they are defined (as opposed to executed) and allows for closures to be created; A closure is created when a function has keeps a link to it's parent scope even after the parent has returned.
Putting var wot;
at the beginning of your constructor ought to do it
core.modules.example_module = function(sandbox){
var wot;
wot = 'foo'; //just so you can see it working
console.log('wot from constructor ==', wot);
return{
init : function(){
console.log('wot from init ==', wot);
}
};
};