动态引用函数时的Javascript变量范围

时间:2014-11-09 00:42:58

标签: javascript

我正在尝试创建一个围绕对象方法创建“代理”的函数。此“代理”将用于处理Web请求,然后调用目标方法。代理功能看起来类似于:

var proxy = function(c) {
  var proxy = {};
  for(var member in c) {
    var args = c[member].toString().match (/function\s*\w*\s*\((.*?)\)/)[1].split (/\s*,\s*/);
    proxy[member] = function(params) {
      var methodArgs = args.map(function(argName) {
        return params[argName];
      });
      return c[member].apply(c, methodArgs);
    }
  }
  return proxy;
};

所以,如果我有这个原始控制器,

var c = {
  sum: function(x, y) {
    return x + y;
  },

  multiply: function(x, y) {
    return x * y;
  }
};

对此调用代理(c)将返回具有sum()和multiply()函数的代理对象。但是,由于proxy()函数中member变量的范围,它总是调用c中最后引用的函数 - 在这种情况下,乘以()。

var cProxy = proxy(c);

//this should call c.sum, but instead calls c.multiply
cProxy.sum({
  x: 3,
  y: 8
});

我如何在proxy()函数中引用正确的函数,以便调用正确的方法?

2 个答案:

答案 0 :(得分:1)

一种方法是将循环内部包装在函数中以创建另一个范围。虽然看起来很奇怪:

    proxy[member] = (function(member) {
        return function(params) {
            var methodArgs = args.map(function(argName) {
                return params[argName];
            });
            return c[member].apply(c, methodArgs);
        };
    })(member);

演示:http://jsfiddle.net/rudiedirkx/t5ovkrw9/

另一种方法是使用let member in c,它创建的范围略小于var,但let尚未在大多数浏览器中使用。

另一种方法是使用.bind将参数或上下文粘贴到函数中。这不起作用,因为你已经在使用上下文和参数。

答案 1 :(得分:1)

以下对我有用,只需为会员创建一个闭包

var proxy = function(c) {
  var proxy = {};
  for(var member in c) {
    !function(member){
        var args = c[member].toString().match (/function\s*\w*\s*\((.*?)\)/)[1].split (/\s*,\s*/);
        proxy[member] = function(params) {
          var methodArgs = args.map(function(argName) {
            return params[argName];
          });
          return c[member].apply(c, methodArgs);
        }
    }(member)
  }
  return proxy;
};



console.log( cProxy.sum({x: 3,y: 8})) // returns 11
console.log( cProxy.multiply({x: 3,y: 8})) //returns 24