如何用动态参数包装javascript函数?

时间:2016-09-14 18:23:12

标签: javascript function dynamic arguments wrapper

我想包装一些动态创建的javascript函数,类似于Daniel在此处接受的答案: How do I store javascript functions in a queue for them to be executed eventually

// Function wrapping code.
// fn - reference to function.
// context - what you want "this" to be.
// params - array of parameters to pass to function.
var wrapFunction = function(fn, context, params) {
    return function() {
        fn.apply(context, params);
    };
}

不同之处在于我希望参数值在执行时是动态的 - 是否可以在参数中传递对变量的引用,这可以在它被包装后更新?

这是我想做的事情:

// I have a function to be wrapped
var sayStuff = function(a,b) {
    console.log(a);
    console.log(b);
}

// Variables I'd like to pass
var randomNumberA = 0;
var randomNumberB = 0;

// Wrap the function
var fun = wrapFunction(sayStuff, this, [*reference randomNumberA*,*reference randomNumberB*]);

// variables get changed
randomNumberA = Math.random()*100;
randomNumberB = Math.random()*100;

// Execute the function using current values of randomNumberA & randomNumberB
fun();

如果可能的话我想在不更改sayStuff的情况下这样做,我有很多现有的功能,我希望包装,也可以在包装外使用,所以理想情况下我不想更换一个对象的参数。 希望有道理,谢谢!

2 个答案:

答案 0 :(得分:1)

如果在context参数中定义了动态参数,则解决方案可以基于传递变量的名称,然后在执行时计算其当前值:



var wrapFunction = function(fn, context) {
  var xArg = arguments;
  return function() {
    var argsArray = [];
    for (var i = 2; i < xArg.length; i++) {
      argsArray.push(context[xArg[i]]);
    }
    fn.apply(context, argsArray);
  };
}

var sayStuff = function() {
  for (var i = 0; i < arguments.length; i++) {
    console.log('sayStuff func: ' + arguments[i]);
  }
}

var randomNumber1 = 0;
var randomNumber2 = 0;

var fun = wrapFunction(sayStuff, this, 'randomNumber1', 'randomNumber2');

randomNumber1 = Math.random()*100;
randomNumber2 = Math.random()*100;

console.log('randomNumber1: ' + randomNumber1);
console.log('randomNumber2: ' + randomNumber2);

fun();
&#13;
&#13;
&#13;

答案 1 :(得分:1)

如果函数和变量将在同一范围内创建,您可以使用它:

var randomNumber = 0;
var fun = function(){ alert(randomNumber); }

randomNumber = 10;

// Now this will alert 10, because when fun is executed
// JS looks in his scope to find what randomNumber is.
fun();

这是因为javascript中的函数用作Closures,它们随身携带它们的环境。请参阅:https://en.wikipedia.org/wiki/Closure_(computer_programming)

因此,如果将randomNumber更改为绑定该函数的范围,则需要使用一个对象,这是因为在javascript中我们没有&#34;指针&#34;或引用通过。一种方法是使用对象。

function giveMeAFunction(){
  var params = { randomNumber: 0 }
  var fun = function(){ alert(scope.randomNumber); }
  return {fun: fun, scope: scope};
}

var paramsAndFun = giveMeAFunction()
// Now you can change the variables in the scope and call the function
paramsAndFun.params.randomNumber = 10;
paramsAndFun.fun(); // Will alert 10

// Now if you replace the entire params object it will not work
// This is because you will replacing it with a new object while
// The one that is referenced in the scope where fun was created is
// the old one.
paramsAndFun.params = { randomNumber: 15 };
paramsAndFun.fun(); // will still alert 10

现在让我们解决部分问题。

已经有Function.prototype.bind功能可以帮助您。

例如:

var sayStuff = function(opts) {
    alert(otions.randomNumber);
}

var options = { randomNumber: 0 };
var fun = sayStuff.bind(this, options);

options.randomNumber = 10;

fun(); // Will print 10

这里有很多事情要发生。对不起,如果我把一切都搞糊涂了。