views:

445

answers:

3

If you want to use global functions and variable dynamically you can use:

window[functionName](window[varName]);

Is it possible to do the same thing for variables in the local scope?

This code works correctly but currently uses eval and I'm trying to think of how else to do it.

var test = function(){
    //this = window
    var a, b, c; //private variables

    var prop = function(name, def){
     //this = window
     eval(name+ ' = ' + (def.toSource() || undefined) + ';'); 

     return function(value){
      //this = test object
      if ( !value) {
       return eval('(' + name + ')');
      }
      eval(name + ' = value;')
      return this;
     };

    };

    return {
     a:prop('a', 1),
     b:prop('b', 2),
     c:prop('c', 3),
     d:function(){
      //to show that they are accessible via to methods
      return [a,b,c];
     }
    };
}();

>>>test
Object
>>>test.prop
undefined
>>>test.a
function()
>>>test.a()
1 //returns the default
>>>test.a(123)
Object //returns the object
>>>test.a()
123 //returns the changed private variable
>>>test.d()
[123,2,3]
A: 

Hopefully I'm not over-simplifying, but what about something as simple as using an object?

var test = {
    getValue : function(localName){
     return this[localName];
    },
    setValue : function(localName, value){
     return this[localName] = value;
    }
};

>>> test.a = 123
>>> test.getValue('a')
123
>>> test.a
123

>>> test.setValue('b', 999)
999
>>> test.b
999
If you're going to just access the object's local variables directly, what's the point of even defining a getter or setter?
Daniel Lew
There isn't one. I just added that in so the usage would be identical to Annan's example. I agree, it would be completely stupid in practice.
The reason for the code is to emulate how getters and setters work in a cross browser way. Therefore my original code was incorrect (now fixed) as the variables prop() created weren't available to the rest of the object. Your way allows direct access and manipulation of properties.
Annan
+2  A: 

To answer your question, no, there is no way to do dynamic variable lookup in a local scope without using eval().

The best alternative is to make your "scope" just a regular object [literal] (ie, "{}"), and stick your data in there.

Crescent Fresh
+2  A: 

No, like crescentfresh said. Below you find an example of how to implement without eval, but with an internal private object.

var test = function () {
  var prv={ };
  function prop(name, def) {
    prv[name] = def;
    return function(value) {
      // if (!value) is true for 'undefined', 'null', '0', NaN, '' (empty string) and false.
      // I assume you wanted undefined. If you also want null add: || value===null
      // Another way is to check arguments.length to get how many parameters was
      // given to this function when it was called.
      if (typeof value === "undefined"){
        //check if hasOwnProperty so you don't unexpected results from
        //the objects prototype.
        return Object.prototype.hasOwnProperty.call(prv,name) ? prv[name] : undefined;
      }
      prv[name]=value;
      return this;
    }
  };

  return pub = {
    a:prop('a', 1),
    b:prop('b', 2),
    c:prop('c', 3),
    d:function(){
      //to show that they are accessible via two methods
      //This is a case where 'with' could be used since it only reads from the object.
      return [prv.a,prv.b,prv.c];
    }
  };
}();
some