How can I access local scope dynamically in javasc

2019-01-01 11:26发布

问题:

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]

回答1:

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];
    }
  };
}();


回答2:

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.



回答3:

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