Have the scope accessible as an object and implement a new with operator / block

Xavier MONTILLET xavierm02.net at gmail.com
Tue Dec 20 02:12:39 PST 2011


Hi,

There is this one thing in JavaScript I really hate: You can't so
{{$varName}} as in PHP so as soon as you need dynamic names, you have
to put everything in an object...

I don't know how scopes are implemented but there should be a "not so
hard" way to make them available as JS objects. The same way window
(or global or self or whatever) works for the global scope. Something
like this:

var a = { };
var b = [ ];
window[ 'a' ] === a;// true
window[ 'b' ] === b;// true
( function ( ) {
    var a = { };
    var b = [ ];
    scope[ 'a' ] === a;// -> true
    scope[ 'b' ] === b;// -> true
}( ) );





And the scope would inherit the parent scope. Here (this code would be
"inside the function":

var scope = Object.create( window, {
    a: {
        value: a,
        enumerable: true,
        writable: true,
        configurable: true
    },
    // same with b
} );





About the properties:
- enumerable true seems obvious
- writable too, except for variable declared with const
- configurable, I'd say false since you cannot use delete on variables
declared with var. But if you want the same behavior as window, then
variables declared with var would have configurable=false and the ones
declared as properties of the scope would have configurable=true.

var a = { };
window.b = { };
console.log( delete a );// false
console.log( delete b );// true
console.log( a );// Object
console.log( b );// ReferenceError: b is not defined

I always though this behavior was strange but since it is and doesn't
bother anyone...




About security, maybe Object.getPrototypeOf should throw an error on
scopes. Because having a child scope change your variables could be
strange... But that would only be a problem for scripts made with
third-party scripts included in own scripts that declare "fake"
variables to remove access to some features:

( function ( ) {
    var window, setTimeout, undefined;
    ( function ( ) {// this function is from third party. It got
inserted in this code to make it "safer"
        // whatever but can't access setTimeout
    ).call( undefined );
}( ) );

And without Object.getPrototypeOf and scope:

( function ( ) {
    var window, setTimeout, undefined;
    ( function ( ) {// this function is from third party. It got
inserted in this code to make it "safer"
        Object.getPrototypeOf( Object.getPrototypeOf( scope )
).setTimeout( function( ) { }, 100 );// you can access setTimout
    ).call( undefined );
}( ) );






This might not seam that useful but when you think about the with
"operator" from ES 3, if you add this scope thing, it becomes easy to
make it work "properly".

I don't know how we could call it but what it would do is setting the
"inner" scope to an object. So ALL "variables" in that block would be
the object's properties and it would "remove" any other variable.

Here is an example:

( function ( ) {
    var a = 'a';
    var b = 'b';
    var o = {
        b: 'B',
        c: 'C'
    };
    // here, scope == { a: 'a', b: 'b', o: { b: 'B', c: 'C' } }
    with ( o ) {
        // /!\ scope is still the same!
        // otherwise you would have no access to "real" variables
        b;// 'B'
        c;// 'C'
        try {
            a;
        } catch ( e ) {
            e;// ReferenceError: a is not defined
        }
        scope.a;// 'a'
        scope.b;// 'b'
        scope.c;// undefined
    }
} )( );





What do you think?


More information about the es-discuss mailing list