你能动态地将局部变量添加到函数中吗?

时间:2012-01-19 20:01:15

标签: javascript

我正在使用对象来命名我的JavaScript代码。这些对象通常包含使用thisapply - 指针映射到对象本身的函数。但是,我发现每次我想访问对象的其他函数或属性时都使用this - 指针是不方便的,特别是因为在很多情况下我使用new - 运算符来使用函数对象你使用类的方式。如果new Line(),我宁愿写new this.Line()

如果你可以像php一样用extract方式将局部变量添加到函数中,那将是很好的(伪代码跟随,它有点复杂)

var sample_object = {
  "some_function": function() {}
}

test() {
  extract(sample_object);
  some_function();   // imported from sample_object
}

这甚至可能吗?

3 个答案:

答案 0 :(得分:5)

我很确定eval是你唯一的答案;但你需要知道,如果你的控制之外有任何输入,那就不安全了

function dynamicArgs (varName, varValue) {
  eval("var " + varName + "=" + JSON.encode(varValue) );
  alert(a);
}

dynamicArgs("a", "value");

你可以看到这个问题。如果动态变量不知道它的名字,你的函数应该如何调用?我把它硬编码到一个变量,因为我在调用它时传递它,但这不是一个好的解决方案。唯一的解决方案是另一个eval。你真的应该考虑你需要做什么以及这是否有用。但这是可行的。

这里有效:http://jsfiddle.net/mendesjuan/GG3Wu/

function dynamicArgs (varName, varValue) {
  eval('var ' + varName + "='" + varValue + "';");
  alert(eval(varName));
}

dynamicArgs("f", "Here I am");

现在这里有一个例子,就像你正在做的那样,从this.MyConstructor创建一个变量 http://jsfiddle.net/mendesjuan/AK3WD/

var ns = {
    MyConstructor: function(val) {
       this.prop = val;
    },

    runConstructor: function(val) {
      var Ctor = "MyConstructor";
      eval('var ' + Ctor + ' =  this.' + Ctor);
      return new MyConstructor(val);
    }
}


alert( ns.runConstructor("Hello").prop );

如果您想将对象的所有值导入范围,这是一个示例;

http://jsfiddle.net/mendesjuan/AK3WD/1/

var ns = {
    MyConstructor: function(val) {
       this.val= val;
    },

    anotherProperty: 5,

    runConstructor: function(val) {
        // Bring all the variables from this into this scope
        for (var prop in this) {
            eval('var ' + prop + ' =  this.' + prop);
        }
        alert('Testing var anotherProperty: ' + anotherProperty);
        var obj =  new MyConstructor(val);
        alert('Created MyConstructor: its prop is ' + obj.val)
    }
}


ns.runConstructor("Hello");

答案 1 :(得分:3)

存在争议with,其中有一些great applications,但速度稍慢且容易出错。它在严格模式下抛出一个错误(你应该总是选择加入)并且不推荐使用。

var sampleObject = {
  someFunction: function() {},
  b: 10
}

with (sampleObject) {
    typeof someFunction // "function"

    var a = 42
    var b = 20
}

sampleObject.a // undefined
sampleObject.b // 20

请注意,with - 块中定义的新变量不会添加到对象中。然而,如果对象中已经有一个同名属性,则会修改此属性(感谢@Rocket)。

只是为了好玩,这里是an implementation of extract使用eval(这比with更邪恶)。您可以使用它做不可言说的事情,例如,如果您的对象具有sampleObject['x; while (true) { alert("Hi!") }']等属性。

答案 2 :(得分:1)

我就这样做了:

   function smObject ( object) {
    return function () {
        function getter(prop) {
            return function() {
                return this[prop];
            }
        }

        function setter(prop) {
            return function(data) {
                this[prop]=data;
            }
        }

        for (var o = 0; o < object.length; o++) {
            this[object[o]] = {};
            this['get' + object[o]] = getter(object[o]);
            this['set' + object[o]] = setter(object[o]);
        }
    }
}

现在你可以实例化一个这样的函数:

var fields = ['Name', 'Id', 'Other', '....' ]
var MyFunction = smObject( fields );
var myObject = new MyFunction();

// getter/setters
myObject.setId(5);
myObject.getId(); // will return 5

此致 Emanouil