【问题标题】:Inject variable into function's scope将变量注入函数的作用域
【发布时间】:2013-03-21 19:14:48
【问题描述】:

所以,我想做这样的事情:

    var a = 'a';

    var dummy = function() {

        // Print out var 'a', from the scope above
        console.log('Dummy a: ' + a);

        // Print out 'b', from the 'compelled' scope
        console.log('Dummy b: ' + b);
    }

    (function() {

        var b = 'otherscope';

        // I know apply won't work, I also don't want to merge scopes
        dummy.apply(this);

        // I want something like this:
        dummy.compel(this, [], {b: 'injected!'});

    })();

但这行不通。

我实际上并不希望函数能够达到 2 个作用域,我希望能够从外部设置虚拟函数内部使用的 'b' 变量。

【问题讨论】:

  • 执行此操作的应用程序是什么?人们可能会建议其他技术
  • 也许这是一个(复杂的)解决方法:stackoverflow.com/questions/10060857/…
  • 我主要是想看看有没有可能。好吧,我实际上想在 node.js MVC 中使用它。我不喜欢每个动作都设置参数,这样会更好。 @bfavaretto 向我展示了一个不错的解决方法,尽管我担心使用 eval() 会对性能造成太大影响:)

标签: javascript node.js


【解决方案1】:

您可以将b 设为函数的参数或全局变量。

var a = 'a';
var dummy = function(b) {
   ...
}

var a = 'a';
var b;
var dummy = function() {
   ...
}

第一个允许您选择虚拟函数何时可以访问变量,第二个允许您在任何地方访问它。

【讨论】:

  • 至于为什么:JavaScript使用词法作用域,所以作用域在函数对象被创建的那一刻就附加到函数对象上。当函数被调用时,不可能在作用域中注入一些东西。
【解决方案2】:

所以,我找到了一种更快的方法来做这样的事情:

var C = function(ctx, funcBody){
        var newBody = [];

        for(var k in ctx){
            var i =  "var "+k + " = ctx['"+k+"'];";
            newBody.push(i);
        }
        var res = "return function(t){ " +funcBody+ " }";
        newBody.push(res);
        var F = new Function("ctx", newBody.join('\n'));
        return F(ctx);
}
var newFunction = C({"foo":10, "bar":100}, "return foo+bar*t")
newFunction(50);

【讨论】:

    【解决方案3】:

    使用这个:

    Function.prototype.applyVars = function(scope, params, scope_variables) {
      if (scope_variables) {
        var variable, defVars = [];
        for (variable in scope_variables) {
          if (scope_variables.hasOwnProperty(variable)) {
            defVars.push(variable + '=scope_variables["' + variable + '"]');
          }
        }
        eval('var ' + defVars.join(',') + ';');
        return eval('(' + this + ').apply(scope, params);');
      }
      return this.apply(scope, params);
    }
    
    // Example
    
    function foo(p1) {
      document.write('Variable [p1]: ', p1);
      document.write('<br />');
      document.write('Variable [x]: ', x);
      document.write('<br />');
      document.write('Variable [y]: ', y);
    }
    
    foo.applyVars(this, ['param X'], { x: "1'2\"3", y: false });

    或者这个:

    function callWithVars(fn, scope, params, scope_variables) {
      if (scope_variables) {
        var variable, defVars = [];
        for (variable in scope_variables) {
          if (scope_variables.hasOwnProperty(variable)) {
            defVars.push(variable + '=scope_variables["' + variable + '"]');
          }
        }
        eval('var ' + defVars.join(',') + ';');
        return eval('(' + fn + ').apply(scope, params);');
      }
      return fn.apply(scope, params);
    }
    
    // Example
    
    function foo(p1) {
      document.write('Variable [p1]: ', p1);
      document.write('<br />');
      document.write('Variable [x]: ', x);
      document.write('<br />');
      document.write('Variable [y]: ', y);
    }
    
    callWithVars(foo, this, ['param X'], { x: "1'2\"3", y: false });

    【讨论】:

    • 如果foo() 在闭包内,并且foo() 在闭包内调用另一个函数,这将不起作用。
    猜你喜欢
    • 2016-06-04
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 2016-02-15
    相关资源
    最近更新 更多