【问题标题】:Call nested function based on input parameter根据输入参数调用嵌套函数
【发布时间】:2023-11-07 23:25:01
【问题描述】:

我有这样的功能。

function myfun(input1, input2, input3){
    //
    // Other codes which deals with input2 and input3 (irrelevant)
    //
    function a(){
        console.log('func a');
    }
    function b(){
        console.log('func b');
    }
    function c(){
        console.log('func c');
    }
    function d(){
        console.log('func d');
    }
    // input1 is an array
    for(var i=0; i<input1.length; i++){
        var name = input1[i];
        name(); // Doesn't work as 'name' refers to a string;
        this[name](); // Doesn't work;
        // How can i execute the nested function whose name is stored in input array ?
    }
}
myfun(['b','d'], 'foo', 'bar');

如何调用 input1 数组中给定名称的嵌套函数?

谢谢。

【问题讨论】:

  • 由于您的代码中有this[name]();,请查看MDN article about this,以更好地了解它是如何工作的。

标签: javascript closures nested-function


【解决方案1】:

编辑

正如@Felix 所建议的,有一种更好的方法(在效率方面)可以做到这一点 -

var myfun = (function () {
    var util = {
        a: function (){
            console.log('method a');
        },
        b: function (){
            console.log('method b');
        },
        c: function (){
            console.log('method c');
        },
        d: function (){
            console.log('method d');
        }
    };

    return function (input1, input2, input3) {
        for(var i=0; i<input1.length; i++){
            var name = input1[i];
            util[name]();
        }
    };
}());

myfun(['b','d'], 'foo', 'bar');

这样util 对象将只构造一次,而在以前的方式中,每次调用myfun 时都会构造对象。

但是,请注意,在这种情况下,内存占用会比前一个更大,因为对util 的引用由于关闭而将始终存储在内存中。


与其创建内部函数,不如尝试使用方法创建对象 -

function myfun(input1, input2, input3){
    var util = {
        a: function (){
            console.log('method a');
        },
        b: function (){
            console.log('method b');
        },
        c: function (){
            console.log('method c');
        },
        d: function (){
            console.log('method d');
        }
    };

    for(var i=0; i<input1.length; i++){
        var name = input1[i];
        util[name]();
    }
}

myfun(['b','d'], 'foo', 'bar');

【讨论】:

  • 并且根据这些内部函数的性质,您可以使用 IIFE 只创建一次对象,并且仍然无法从外部访问这些函数。例如。 var myfun = (function() { var util = {}; return function(input1, ...) { ... }; }());.
  • @FelixKling:是的,你完全正确,我错过了。感谢您的意见,我已经编辑了我的答案!
【解决方案2】:

替换名称(); with eval(name + '()');

【讨论】:

  • 我不会为此建议eval。最好避免使用eval的习惯。
【解决方案3】:

编辑:

您必须使函数成为对象的成员。

var funcFactory = {
    a:function(){
        console.log('func a');
    },
    b:function(){
        console.log('func b');
    },
    c:function(){
        console.log('func c');
    },
    d:function(){
        console.log('func d');
    },
    call:function(input1, input2, input3){     
        for(var i=0; i<input1.length; i++){
           var name = input1[i];
            this[name](); // Doesn't work;
        }
    }
}
funcFactory.call(['b','d'],foo,bar);

【讨论】:

  • 鉴于 OP 的代码,这将使函数全局化,因为 this 将引用 window。您没有使函数成为外部函数的“成员”。
  • 是的,我试过这个,但正如@FelixKling 所说,它创建了这个引用窗口。
  • 啊,对。您需要将它们放在对象中 {a:function(){}...}