JavaScript has lexical scoping which means that non-local variables accessed from within a function are resolved to variables present in the parents' scope of that function when it was defined. This is in contrast to dynamic scoping in which non-local variables accessed from within a function are resolved to variables present in the calling scope of that function when it is called.
x=1
function g () { echo $x ; x=2 ; }
function f () { local x=3 ; g ; }
f # does this print 1, or 3?
echo $x # does this print 1, or 2?
The above program prints 1 and then 2 in a lexically scoped language, and it prints 3 and then 1 in a dynamically scoped language. Since JavaScript is lexically scoped it will print 1 and then 2 as demonstrated below:
var print = x => console.log(x);
var x = 1;
function g() {
print(x);
x = 2;
}
function f() {
var x = 3;
g();
}
f(); // prints 1
print(x); // prints 2
Although JavaScript doesn't support dynamic scoping we can implement it using eval
as follows:
var print = x => console.log(x);
var x = 1;
function g() {
print(x);
x = 2;
}
function f() {
// create a new local copy of `g` bound to the current scope
// explicitly assign it to a variable since functions can be unnamed
// place this code in the beginning of the function - manual hoisting
var g_ = eval("(" + String(g) + ")");
var x = 3;
g_();
}
f(); // prints 3
print(x); // prints 1
I would like to know if there exists another possible way to achieve the same result without resorting to eval
.
Edit: This is what I'm trying to implement without using eval
:
var print = x => console.log(x);
function Class(clazz) {
return function () {
var constructor;
var Constructor = eval("(" + String(clazz) + ")");
Constructor.apply(this, arguments);
constructor.apply(this, arguments);
};
}
var Rectangle = new Class(function () {
var width, height;
constructor = function (w, h) {
width = w;
height = h;
};
this.area = function () {
return width * height;
};
});
var rectangle = new Rectangle(2, 3);
print(rectangle.area());
I know that it's not a very good example but the general idea is to use dynamic scoping to create closures. I think this pattern has a lot of potential.
eval
. – Crosswaysuber
that points to the parent of the given class. This variable should be accessible to the class scope but it shouldn't be accessible to the public. Hence I can't just set it on the instance of the class and call it a day. Thus the roundabout workaround. – Crosswaysg
can't access the local variables off
unless it's defined inf
. That's the reason I didvar g = eval(String(g))
. In your case it's just like my first example above (the one without dynamic scoping). Even worse you're explicitly setting global variables by usingthis
. – Crosswaysthis
. I'm pretty sure usingeval
is the only way to do that. However like every programmer should I have learned to embrace the language instead of fighting it. So I don't need dynamic scoping anymore. I've found a better solution to my problem in functional programming, and I've used my newfound knowledge to create a very small and efficient JavaScript library for object oriented and functional programming - augment. =) – Crossways