ChatGPT解决这个技术问题 Extra ChatGPT

当我将其名称作为字符串时如何执行 JavaScript 函数

我将 JavaScript 中的函数名称作为字符串。如何将其转换为函数指针,以便以后调用它?

根据具体情况,我可能还需要将各种参数传递给方法。

某些函数可能采用 namespace.namespace.function(args[...]) 的形式。


L
Liam

除非您绝对、肯定别无选择,否则不要使用 eval

如前所述,使用类似这样的方法是最好的方法:

window["functionName"](arguments);

但是,这不适用于命名空间的函数:

window["My.Namespace.functionName"](arguments); // fail

这就是你要这样做的方式:

window["My"]["Namespace"]["functionName"](arguments); // succeeds

为了使这更容易并提供一些灵活性,这里有一个方便的功能:

function executeFunctionByName(functionName, context /*, args */) {
  var args = Array.prototype.slice.call(arguments, 2);
  var namespaces = functionName.split(".");
  var func = namespaces.pop();
  for(var i = 0; i < namespaces.length; i++) {
    context = context[namespaces[i]];
  }
  return context[func].apply(context, args);
}

你会这样称呼它:

executeFunctionByName("My.Namespace.functionName", window, arguments);

注意,你可以传入任何你想要的上下文,所以这和上面的一样:

executeFunctionByName("Namespace.functionName", My, arguments);

你知道你不需要整个“func”结构吗?单独使用“context.apply”就可以了
当然,我知道——但我编写函数的方式为那些阅读它的人提供了一些清晰度,可能无法完全理解正在发生的事情。我写了这个函数,意识到阅读它的人可能需要一些帮助。不过,我会提供一个替代方案,因为你问...
从头开始 - 代码足够清晰,知道的人知道。如果您像我一样,并且知道自己在做什么,那么如果您使用此代码,则可以自己进行此类更改。 Stack Overflow 是用来教育别人的,我觉得我的代码对于新手来说更容易理解。不过谢谢!
是否存在 window["funcName"] 会返回 undefined 的情况?这就是我目前遇到的问题。调用代码和函数定义在两个单独的 js 文件中。我尝试将它们添加到同一个文件中,但这没有任何区别。
我觉得这里有问题。当您调用 My.Namespace.functionName() 时,this 将引用 My.Namespace 对象。但是当您调用 executeFunctionByName("My.Namespace.functionName", window) 时,没有办法让 this 引用相同的东西。也许它应该使用最后一个命名空间作为范围,或者如果没有命名空间,则使用 window。或者您可以允许用户将范围指定为参数。
C
Community

只是想我会发布一个稍微改动过的 Jason Bunting's very helpful function 版本。

首先,我通过向 slice() 提供第二个参数来简化第一条语句。原始版本在除 IE 之外的所有浏览器中都可以正常工作。

其次,我在 return 语句中用上下文替换了它;否则,在执行目标函数时,它总是指向窗口。

function executeFunctionByName(functionName, context /*, args */) {
    var args = Array.prototype.slice.call(arguments, 2);
    var namespaces = functionName.split(".");
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
    }
    return context[func].apply(context, args);
}

没有检查“functionName”是否真的存在?
我认为 Mac 的回答被低估了。我不是专家,但它似乎经过深思熟虑且稳健。
C
Community

这个其他问题的答案向您展示了如何做到这一点:Javascript equivalent of Python's locals()?

基本上可以说

window["foo"](arg1, arg2);

或者正如许多其他人所建议的那样,您可以只使用 eval:

eval(fname)(arg1, arg2);

虽然这是非常不安全的,除非你完全确定你正在评估什么。


第一种形式更可取
仅当所有其他方法都失败时,才将 eval 用作最后的手段。
它是......但它可以与这样的函数一起使用:xyz(args)吗?
@keiron:是的。请看下面我的回答
R
Ruben Daddario

我认为这样做的一种优雅方法是在哈希对象中定义你的函数。然后,您可以使用字符串从哈希中引用这些函数。例如

var customObject = {
  customFunction: function(param){...}
};

然后你可以调用:

customObject['customFunction'](param);

其中 customFunction 将是与对象中定义的函数匹配的字符串。

更新

似乎这个答案对许多其他编码员都有帮助,所以这里有一个更新版本。

使用 ES6,您还可以使用计算属性名称,这将允许您避免使用魔法字符串。

const FunctionNames = Object.freeze({ FirstFunction: "firstFunction", SecondFunction: "secondFunction" }); ... var customObject = { [FunctionNames.FirstFunction]: function(param){...}, [FunctionNames.SecondFunction]: function(param){...} }; ... customObject[FunctionNames.FirstFunction](param);


@ibsenv,感谢您的评论,以帮助我将此回复确定为最佳回复。我创建了一个函数对象数组,然后用它来创建一个 deferred.promises 数组。我在下面放了一些示例代码。 (我不想创建新的回复并借用鲁本的回复。)
function getMyData(arrayOfObjectsWithIds) { var functionArray = arrayOfObjectsWithIds.map( function (value) { return {myGetDataFunction: MyService.getMyData(value.id)}; }) var promises = functionArray.map( function (getDataFunction) { var deferred =$ q.defer(); getDataFunction.myGetDataFunction.success( function(data) { deferred.resolve(data) }).error( function (error) { deferred.reject(); }); return deferred.promise; }); $q.all(promises).then( function (dataArray) { //do stuff }) };
这很好用,我只添加下划线/lodash 来验证它是否是一个函数。然后运行
C
Coley

你能不能这样做:

var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();

您还可以使用此方法执行任何其他 JavaScript。


当函数传递偶数参数时有效
函数返回呢?
这与 eval("My.Namespace.functionName()"); 有何不同?
@PeterDeenv 只需将第一行更改为 var codeToExecute = "return My.Namespace.functionName()";
@developerbmw,这是答案stackoverflow.com/questions/4599857/…
n
nils petersohn

使用 ES6,您可以按名称访问类方法:

class X {
  method1(){
    console.log("1");
  }
  method2(){
    this['method1']();
    console.log("2");
  }
}
let x  = new X();
x['method2']();

输出将是:

1
2

最好的javascript PURE ...上帝..删除类不起作用,但没关系。谢谢!
这是我长期以来一直在寻找的东西。谢谢!
ES2015 与这里无关。您可以使用纯对象或通过 Object.create() 委托原型来实现相同的目标。 const myObj = { method1() { console.log('1') }, method2() { console.log('2') } } myObj['method1'](); // 1 myObj['method2'](); // 2
这是黄金!!!我很惊讶我以前从未想过这一点。好的!!!
我也认为这是实现我们目标的最佳方式。
a
annakata

两件事情:

避免评估,这是非常危险和缓慢的

其次,你的函数存在于哪里并不重要,“全局”是无关紧要的。 xyfoo() 可以通过 xy['foo']() 或 x['y']['foo']() 甚至 window['x']['y']['foo']() 来启用。你可以像这样无限地链接。


但是你不能用 window['xyz']() 来调用 xyz()
W
Wolfgang Kuehn

所有答案都假设可以通过全局范围(窗口)访问这些函数。但是,OP 没有做出这个假设。

如果函数位于本地范围内(也称为闭包)并且没有被其他本地对象引用,那么运气不好:您必须使用 eval() AFAIK,请参阅 dynamically call local function in javascript


伙计(或dudette),非常感谢您指出这一点!我以为我要疯了一秒钟。
如果它在本地对象中,您可以这样做:localobject['function_name'](),与 window['function_name']() 相同
Z
Zibri

根据您所在的位置,您还可以使用:

this["funcname"]();
self["funcname"]();
window["funcname"]();
top["funcname"]();
globalThis["funcname"]();

或者,在 nodejs 中

global["funcname"]()

感谢这个答案,可以做function callObjectMethod(obj,meth){ return (_v) => { obj[meth](_v) } }。对我来说,调用一些带有来自外部服务回调的参数的对象方法很有用。希望这对其他人有帮助。
R
Rob W

您只需通过 window[<method name>] 将字符串转换为指针。例子:

var function_name = "string";
function_name = window[function_name];

现在你可以像指针一样使用它了。


这似乎是一种更安全的方式。
M
Mac

这是我对 Jason Bunting / Alex Nazarov 出色答案的贡献,其中包括 Crashalot 要求的错误检查。

鉴于这个(人为的)序言:

a = function( args ) {
    console.log( 'global func passed:' );
    for( var i = 0; i < arguments.length; i++ ) {
        console.log( '-> ' + arguments[ i ] );
    }
};
ns = {};
ns.a = function( args ) {
    console.log( 'namespace func passed:' );
    for( var i = 0; i < arguments.length; i++ ) {
        console.log( '-> ' + arguments[ i ] ); 
    }
};
name = 'nsa';
n_s_a = [ 'Snowden' ];
noSuchAgency = function(){};

然后是以下功能:

function executeFunctionByName( functionName, context /*, args */ ) {
    var args, namespaces, func;

    if( typeof functionName === 'undefined' ) { throw 'function name not specified'; }

    if( typeof eval( functionName ) !== 'function' ) { throw functionName + ' is not a function'; }

    if( typeof context !== 'undefined' ) { 
        if( typeof context === 'object' && context instanceof Array === false ) { 
            if( typeof context[ functionName ] !== 'function' ) {
                throw context + '.' + functionName + ' is not a function';
            }
            args = Array.prototype.slice.call( arguments, 2 );

        } else {
            args = Array.prototype.slice.call( arguments, 1 );
            context = window;
        }

    } else {
        context = window;
    }

    namespaces = functionName.split( "." );
    func = namespaces.pop();

    for( var i = 0; i < namespaces.length; i++ ) {
        context = context[ namespaces[ i ] ];
    }

    return context[ func ].apply( context, args );
}

将允许您按存储在命名空间或全局字符串中的名称调用 javascript 函数,带或不带参数(包括 Array 对象),提供对遇到的任何错误的反馈(希望能捕获它们)。

示例输出显示了它是如何工作的:

// calling a global function without parms
executeFunctionByName( 'a' );
  /* OUTPUT:
  global func passed:
  */

// calling a global function passing a number (with implicit window context)
executeFunctionByName( 'a', 123 );
  /* OUTPUT:
  global func passed:
  -> 123
  */

// calling a namespaced function without parms
executeFunctionByName( 'ns.a' );
  /* OUTPUT:
  namespace func passed:
  */

// calling a namespaced function passing a string literal
executeFunctionByName( 'ns.a', 'No Such Agency!' );
  /* OUTPUT:
  namespace func passed:
  -> No Such Agency!
  */

// calling a namespaced function, with explicit context as separate arg, passing a string literal and array 
executeFunctionByName( 'a', ns, 'No Such Agency!', [ 007, 'is the man' ] );
  /* OUTPUT:
  namespace func passed:
  -> No Such Agency!
  -> 7,is the man
  */

// calling a global function passing a string variable (with implicit window context)
executeFunctionByName( 'a', name );
  /* OUTPUT:
  global func passed:
  -> nsa
  */

// calling a non-existing function via string literal
executeFunctionByName( 'n_s_a' );
  /* OUTPUT:
  Uncaught n_s_a is not a function
  */

// calling a non-existing function by string variable
executeFunctionByName( n_s_a );
  /* OUTPUT:
  Uncaught Snowden is not a function
  */

// calling an existing function with the wrong namespace reference
executeFunctionByName( 'a', {} );
  /* OUTPUT:
  Uncaught [object Object].a is not a function
  */

// calling no function
executeFunctionByName();
  /* OUTPUT:
  Uncaught function name not specified
  */

// calling by empty string
executeFunctionByName( '' );
  /* OUTPUT:
  Uncaught  is not a function
  */

// calling an existing global function with a namespace reference
executeFunctionByName( 'noSuchAgency', ns );
  /* OUTPUT:
  Uncaught [object Object].noSuchAgency is not a function
  */

不知道......这是一个非常好的努力,很清楚。但对我来说听起来“太宽泛”了......
嗯? SO是一个问答/教学平台。我很乐意提供我能想到的所有例子,希望能传达启发。对我来说,这就是重点。
如果您无论如何都在评估 functionName,为什么不直接使用它呢?
这对我不起作用。我有一个命名空间函数 abcd,其中 d 是函数名。调用 executeFunctionByName("abcd", window) 在检查 if( typeof context[ functionName ] !== 'function' ) 的线上失败,因为上下文 - 窗口 - 已定义,是一个对象和一个数组,但 window['abcd'] 不存在,因为被确定为问题在接受的答案中:window["My.Namespace.functionName"](arguments); // fail
A
Ahmet DAL

如果您想使用 window["functionName"] 调用对象的函数而不是全局函数。你可以这样做;

var myObject=new Object();
myObject["functionName"](arguments);

例子:

var now=new Date();
now["getFullYear"]()

d
dykstrad

当心!!!

应该尽量避免在 JavaScript 中通过字符串调用函数,原因有二:

原因 1:某些代码混淆器会破坏您的代码,因为它们会更改函数名称,使字符串无效。

原因 2:维护使用这种方法的代码要困难得多,因为要找到字符串调用的方法的用法要困难得多。


您的回答说服了我停止在答案之间滚动并放弃使用函数名称作为字符串调用函数的想法,谢谢,先生。
G
Gershom Maes

这是我的 Es6 方法,它使您可以通过函数名称或函数名称来调用函数,还可以将不同数量的参数传递给不同类型的函数:

函数 fnCall(fn, ...args) { 让 func = (typeof fn =="string")?window[fn]:fn; if (typeof func == "function") func(...args); else throw new Error(`${fn} is Not a function!`); } function example1(arg1){console.log(arg1)} function example2(arg1, arg2){console.log(arg1 + " and " + arg2)} function example3(){console.log("No arguments!") } fnCall("example1", "test_1"); fnCall("example2", "test_2", "test3"); fnCall(example3); fnCall("example4"); // 应该在控制台中引发错误


a
abhishekisnot

惊讶地看到没有提到 setTimeout。

要运行不带参数的函数:

var functionWithoutArguments = function(){
    console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);

使用参数运行函数:

var functionWithArguments = function(arg1, arg2) {
    console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");

要运行深度命名空间函数:

var _very = {
    _deeply: {
        _defined: {
            _function: function(num1, num2) {
                console.log("Execution _very _deeply _defined _function : ", num1, num2);
            }
        }
    }
}
setTimeout("_very._deeply._defined._function(40,50)", 0);

这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时对自己的帖子发表评论,一旦您有足够的reputation,您就可以comment on any post
请添加一个示例,说明您将如何使用几个参数调用 runMe
@lexicore 我投票赞成在审查队列中删除,因为它没有明确地为问题提供实质性答案,而且它本身没有什么价值。
这个方法有潜在的巨大缺陷,因为它把执行放到渲染队列的末尾,从而使这个调用异步
我喜欢这个答案,它似乎符合我的要求。
s
snnsnn

我认为您不需要复杂的中间函数或 eval 或依赖于诸如窗口之类的全局变量:

function fun1(arg) {
  console.log(arg);
}

function fun2(arg) {
  console.log(arg);
}

const operations = {
  fun1,
  fun2
};

operations["fun1"]("Hello World");
operations.fun2("Hello World");

// You can use intermediate variables, if you like
let temp = "fun1";
operations[temp]("Hello World");

它也适用于导入的函数:

// mode.js
export function fun1(arg) {
  console.log(arg);
}

export function fun2(arg) {
  console.log(arg);
}
// index.js
import { fun1, fun2 } from "./mod";

const operations = {
  fun1,
  fun2
};

operations["fun1"]("Hello World");
operations["fun2"]("Hello World");

由于它使用属性访问,因此它可以在最小化或混淆中幸存下来,这与您在此处找到的一些答案相反。


C
Community

因此,就像其他人所说,绝对最好的选择是:

window['myfunction'](arguments)

Jason Bunting said 一样,如果您的函数名称包含对象,它将不起作用:

window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work

所以这是我的函数版本,它将按名称执行所有函数(包括或不包括对象):

我的 = { 代码 : { 是 : { nice : function(a, b){ alert(a + "," + b); } } } }; guy = function(){ alert('awesome'); } 函数 executeFunctionByName(str, args) { var arr = str.split('.'); var fn = 窗口[arr[0]]; for (var i = 1; i < arr.length; i++) { fn = fn[ arr[i] ]; } fn.apply(窗口,参数); } executeFunctionByName('my.code.is.nice', ['arg1', 'arg2']); executeFunctionByName('guy');


L
Leo Lanese
  let t0 = () => { alert('red0') }
  var t1 = () =>{ alert('red1') }
  var t2 = () =>{ alert('red2') }
  var t3 = () =>{ alert('red3') }
  var t4 = () =>{ alert('red4') }
  var t5 = () =>{ alert('red5') }
  var t6 = () =>{ alert('red6') }

  function getSelection(type) {
    var evalSelection = {
      'title0': t0,
      'title1': t1,
      'title2': t2,
      'title3': t3,
      'title4': t4,
      'title5': t5,
      'title6': t6,
      'default': function() {
        return 'Default';
      }
    };
    return (evalSelection[type] || evalSelection['default'])();
  }
  getSelection('title1');

更OOP的解决方案...


B
Bradley Shrader

关于 Jason 和 Alex 帖子的更多细节。我发现向上下文添加默认值很有帮助。只需将 context = context == undefined? window:context; 放在函数的开头即可。您可以将 window 更改为您喜欢的任何上下文,然后每次在默认上下文中调用它时都不需要传入相同的变量。


C
Cilan

为了补充 Jason Bunting 的答案,如果您使用的是 nodejs 或其他东西(这也适用于 dom js),您可以使用 this 而不是 window (请记住:eval 是 evil:

this['fun'+'ctionName']();

C
Community

我的代码中有一个非常相似的东西。我有一个服务器生成的字符串,其中包含一个函数名称,我需要将其作为第 3 方库的回调传递。所以我有一个代码,它接受字符串并返回一个指向函数的“指针”,如果没有找到,则返回 null。

我的解决方案与“Jason Bunting's very helpful function* 非常相似,尽管它不会自动执行,并且上下文始终在窗口中。但这可以很容易地修改。

希望这对某人有所帮助。

/**
 * Converts a string containing a function or object method name to a function pointer.
 * @param  string   func
 * @return function
 */
function getFuncFromString(func) {
    // if already a function, return
    if (typeof func === 'function') return func;

    // if string, try to find function or method of object (of "obj.func" format)
    if (typeof func === 'string') {
        if (!func.length) return null;
        var target = window;
        var func = func.split('.');
        while (func.length) {
            var ns = func.shift();
            if (typeof target[ns] === 'undefined') return null;
            target = target[ns];
        }
        if (typeof target === 'function') return target;
    }

    // return null if could not parse
    return null;
}

v
vivek agarwal

这是我最终为我的一个项目实施的一个强大且可重用的解决方案。

一个 FunctionExecutor 构造函数

用法:

let executor = new FunctionExecutor();
executor.addFunction(two)
executor.addFunction(three)

executor.execute("one");
executor.execute("three");

显然,在项目中,所有需要按名称调用的函数的添加都是通过循环完成的。

函数执行器:

function FunctionExecutor() {
  this.functions = {};

  this.addFunction = function (fn) {
    let fnName = fn.name;
    this.functions[fnName] = fn;
  }

  this.execute = function execute(fnName, ...args) {
    if (fnName in this.functions && typeof this.functions[fnName] === "function") {
      return this.functions[fnName](...args);
    }
    else {
      console.log("could not find " + fnName + " function");
    }
  }

  this.logFunctions = function () {
    console.log(this.functions);
  }
}

示例用法:

function two() {
  console.log("two"); 
}

function three() {
  console.log("three");
}

let executor = new FunctionExecutor();
executor.addFunction(two)
executor.addFunction(three)

executor.execute("one");
executor.execute("three");

m
merqlove

还有一些非常有用的方法。

http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx

var arrayMaker = {  
    someProperty: 'some value here',  
    make: function (arg1, arg2) {  
        return [ this, arg1, arg2 ];  
    },
    execute: function_name
};

M
Magnus Smith

我忍不住提到另一个技巧,如果您有未知数量的参数也作为包含函数名称的字符串的一部分传递,这会有所帮助。例如:

var annoyingstring = 'call_my_func(123, true, "blah")';

如果您的 Javascript 在 HTML 页面上运行,您所需要的只是一个不可见的链接;您可以将字符串传递给 onclick 属性,然后调用 click 方法。

<a href="#" id="link_secret"><!-- invisible --></a>

$('#link_secret').attr('onclick', annoyingstring);
$('#link_secret').click();

或者在运行时创建 <a> 元素。


创造性的解决方案,但这不适用于对象或数组类型的参数。
这是在引擎盖下使用 eval ......而且真的在拐弯抹角地做到这一点
c
crazycrv

最简单的方法是像拥有元素一样访问它

window.ClientSideValidations.forms.location_form

window.ClientSideValidations.forms['location_form']

S
SimoAmi

人们一直说 eval 既危险又邪恶,因为它可以运行任意代码。但是,如果您将 eval 与 whitelisting 方法一起使用,假设您知道所有可能需要提前运行的函数名称,则 eval 不再是安全问题,因为输入是 不再随意。白名单是一种良好且常见的安全模式。这是一个例子:

function runDynamicFn(fnName, ...args) { // 也可以从严格控制的配置中获取 const allowedFnNames = ['fn1', 'ns1.ns2.fn3', 'ns4.fn4'];返回 allowedFnNames.includes(fnName) ? eval(fnName)(...args):未定义; } // 测试函数: function fn1(a) { console.log('fn1 called with', a) } runDynamicFn('alert("got you!")') runDynamicFn('fn1', 'foo')


在我看来,这仍然是一个糟糕的实现;最好映射函数:let allowedFns = new Map(); allowedFns.set('fn1', fn1); allowedFns.set('ns1.ns2.fn3', ns1.ns2.fn3); ...。如果 eval 的使用是安全的,那么问题可能可以在没有 eval 的情况下解决:-P
如果你知道所有的函数名,为什么不直接用函数创建一个数组呢?
K
KingRider

看基本:

var namefunction = 'jspure'; // String

function jspure(msg1 = '', msg2 = '') { 
  console.log(msg1+(msg2!=''?'/'+msg2:''));
} // multiple argument

// Results ur test
window[namefunction]('hello','hello again'); // something...
eval[namefunction] = 'hello'; // use string or something, but its eval just one argument and not exist multiple

存在其他类型的函数是类和看看例子 nils petersohn


C
Community

感谢您提供非常有帮助的答案。我在我的项目中使用 Jason Bunting's function

我将它扩展为使用可选超时,因为设置超时的正常方法不起作用。请参阅abhishekisnot's question

function executeFunctionByName(functionName, context, timeout /*, args */ ) { var args = Array.prototype.slice.call(arguments, 3); var namespaces = functionName.split("."); var func = namespaces.pop(); for (var i = 0; i < namespaces.length; i++) { context = context[namespaces[i]]; } var timeoutID = setTimeout( function(){ context[func].apply(context, args)}, timeout );返回超时ID; } var _very = { _deeply: { _defined: { _function: function(num1, num2) { console.log("执行 _very _deeply _defined _function :", num1, num2); } } } } console.log('now wait') executeFunctionByName("_very._deeply._defined._function", window, 2000, 40, 50 );


P
PeterM

这里有几个 executeByName 函数可以正常工作,除非名称包含 方括号 - 我遇到的问题 - 因为我有动态生成的名称。所以上面的函数会在名字上失败,比如

app.widget['872LfCHc']['toggleFolders']

作为补救措施,我也考虑了这一点,也许有人会发现它很有用:

从 CoffeeScript 生成:

var executeByName = function(name, context) {
  var args, func, i, j, k, len, len1, n, normalizedName, ns;
  if (context == null) {
    context = window;
  }
  args = Array.prototype.slice.call(arguments, 2);
  normalizedName = name.replace(/[\]'"]/g, '').replace(/\[/g, '.');
  ns = normalizedName.split(".");
  func = context;
  for (i = j = 0, len = ns.length; j < len; i = ++j) {
    n = ns[i];
    func = func[n];
  }
  ns.pop();
  for (i = k = 0, len1 = ns.length; k < len1; i = ++k) {
    n = ns[i];
    context = context[n];
  }
  if (typeof func !== 'function') {
    throw new TypeError('Cannot execute function ' + name);
  }
  return func.apply(context, args);
}

为了更好的可读性,还要检查 CoffeeScript 版本:

executeByName = (name, context = window) ->
    args = Array.prototype.slice.call(arguments, 2)
    normalizedName = name.replace(/[\]'"]/g, '').replace(/\[/g, '.')
    ns = normalizedName.split "."
    func = context
    for n, i in ns
        func = func[n]

    ns.pop()
    for n, i in ns
        context = context[n];
    if typeof func != 'function'
        throw new TypeError 'Cannot execute function ' + name
    func.apply(context, args)

S
Suat Atan PhD

您也可以在 eval("functionname as string") 中调用 javascript 函数。如下所示:(eval 是纯 javascript 函数)

function testfunc(){
    return "hello world";
}

$( document ).ready(function() {

     $("div").html(eval("testfunc"));
});

工作示例:https://jsfiddle.net/suatatan/24ms0fna/4/


这很好用,而且很简单
而且也很慢。