0

我很好奇这在 JavaScript 中是否可行。

我想要一个可以返回实际内容不同的函数的工厂函数。说这是我们的工厂:

function makeFunction(a, b, c) {
  // Implement me
  return f;
}

我希望它像这样工作:

> makeFunction(true, true, false);
=> function() { do_a(); do_b(); }
> makeFunction(false, true, false);
=> function() { do_b(); }
> makeFunction(true, false, true);
=> function() { do_a(); do_c(); }

撇开这是否是一个好主意不谈……我可以这样做吗?如果是这样,内部需要发生makeFunction什么?

奖励:一般来说,这种模式叫什么?


编辑:我应该澄清一些我想要的东西:使用闭包的理智方法。例如,以下具有正确的效果,但不会改变函数内容/主体:

function makeFunction(a, b, c) {
  return function() {
    if (a) { do_a(); }
    if (b) { do_b(); }
    if (c) { do_c(); }
  }
}
4

5 回答 5

1

您可以使用Function构造函数来完成此操作。例如:

// Globals can be seen by the function we're going to create.
function do_a() { /* stuff */ }
function do_b() { /* stuff */ }
function do_c() { /* stuff */ }

function makeFunction(a, b, c) {
  var contents = [];
  if (a) { contents.push("do_a();"); }
  if (b) { contents.push("do_b();"); }
  if (c) { contents.push("do_c();"); }
  return new Function(contents.join(''));
}

console.log(makeFunction(true, true));
console.log(makeFunction(true, false, false));
console.log(makeFunction(false, true, true));

上面的代码会将以下内容打印到控制台:

function anonymous() {
  do_a();do_b();
}
function anonymous() {
  do_a();
}
function anonymous() {
  do_b();do_c();
}

我相信这满足了问题的要求。一些 JavaScript 库实际上确实使用这种技术来根据程序在运行时的需要来编译极其高效的函数。但是,这种方法有一些明显的缺点:

  • 使用构造函数创建的Function函数仅继承全局范围。根据您的代码需要做什么,这可能会破坏交易。
  • 以这种方式构造函数很慢,因为引擎必须将函数源转换为可执行代码。(注意:这并不意味着创建的函数本身会很慢。实际上它们会正常运行。)
  • 很难写出这样的函数。(引用/取消引用。)
  • 函数内容不能被 lint。
于 2013-08-28T15:06:50.880 回答
1

这个解决方案会为您处理这一切,func使用它们的名称在数组中定义您想要的函数,然后使用它来创建。

function a (){
    console.log("a");
};
function b() {
    console.log("b");
};
function c() {
    console.log("c");
};
function makeFunction() {
    var funcs = [a, b, c];
    var finalfunc = [];
    for (var i = 0; i < arguments.length && i < funcs.length; i++) {
        if (arguments[i]) {
            finalfunc.push(funcs[i]);
        }
    }
    return function () {
        var f = finalfunc;
        for (var a = 0; a < f.length; a++) {
            f[a]();
        }
    };
};

例子:

var z = makeFunction(true);
z();//outputs a

var z = makeFunction(true, false, true);
z();//outputs a c

var z = makeFunction(true, true, false);
z();//outputs a b

var z = makeFunction(true, true, true);
z();//outputs a b c

var z = makeFunction(true, true, true, true);
z();//outputs a b c

编辑

直到我写了它,我才看到你不想要关闭,但无论如何我都会把它留在这里

尽管您已经说过,但这可能是一种更安全的方式。它还直接回答了除此之外的问题,我创建了一个函数,其中只有您希望在其中运行的函数。每个函数都没有 if 语句,它仅取决于您提供的函数和参数:)

它也是完全动态的,不依赖于为每个函数定义条件。

于 2013-08-27T22:59:14.147 回答
1

是的,这是可能的。不,我不会评论这种方法的(感知)价值。

这是一个快速示例:

window.addEventListener('load', mInit, false);

function createFunction(funcName, message)
{
    var script = document.createElement('script');
    var scriptContents = 'function ' + funcName + '()\n';
    scriptContents += '{\n\talert("' + message + '");\n}\n';
    script.appendChild( newTxt(scriptContents) );
    document.head.appendChild(script);
}

function mInit()
{
    createFunction('myFunc', 'hello world');
    myFunc();
}

输出:

<script>function myFunc()
{
    alert("hello world");
}
</script>

我不确定该功能是否会立即起作用,因此测试如上所示。(确实如此,顺便说一句)

过去我有一个想法,涉及将脚本隐藏在图像的 alpha 通道中......

于 2013-08-27T23:00:18.070 回答
0

以下“手动”方法可以完成工作,但仅在您只需要处理几个条件和/或您喜欢打字时才推荐使用。

function makeFunction(a, b, c) {
   if (a && b && c) {
      return function() { do_a(); do_b(); do_c(); }
   }

   if (a && b && !c) {
      return function() { do_a(); do_b(); }
   }

   // You get the idea...
}

优点:有效吗?缺点:如果你需要提供很多排列......祝你好运:)

于 2013-08-27T22:45:57.033 回答
0

您可以使用一个对象并返回它的方法。

不过,我真的不认为这有任何意义。

function makeFunction(a, b) {
 var f = {
    a:function(){console.log("IcanBeANythign")},
    b:function(a,b){return a+b}
  };
  if(a){
  return f.a;
  }
  if(b){
  return f.b;
  }
}
var f = makeFunction(false,true)(3,4) // 7

类似的东西是柯里化或更准确地说是部分应用。这里已经得到了相当彻底的回答

你可以这样做:

function curryPlus(a){
          return function(b){
          return a+b;
          }
    }

var add1 = curryPlus(1);
add1(2) // Outputs: 3
于 2013-08-27T22:57:54.060 回答