Как выполнить функцию JavaScript, когда у меня есть ее имя в виде строки - PullRequest
945 голосов
/ 11 декабря 2008

У меня есть имя функции в JavaScript в виде строки. Как мне преобразовать это в указатель на функцию, чтобы я мог вызвать его позже?

В зависимости от обстоятельств мне может потребоваться передать различные аргументы в метод тоже.

Некоторые функции могут принимать форму namespace.namespace.function(args[...]).

Ответы [ 32 ]

1 голос
/ 29 июня 2014

Чтобы добавить к ответу Джейсона Бантинга, если вы используете nodejs или что-то еще (и это работает в dom js), вы можете использовать this вместо window (и помните: eval - это evil

this['fun'+'ctionName']();
1 голос
/ 29 октября 2015

Я не могу не упомянуть еще один прием, который помогает, если у вас есть неизвестное количество аргументов, которые также передаются как часть строки , содержащей имя функции. Например:

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> во время выполнения.

1 голос
/ 23 ноября 2012

Там тоже есть очень полезный способ.

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
};
0 голосов
/ 02 июня 2018

Поскольку eval() - зло, а new Function() - не самый эффективный способ достичь этого, вот быстрая функция JS, которая возвращает функцию по ее имени в строке.

  • Работает для функций пространства имен
  • Откат к нулевой функции в случае нулевой / неопределенной строки
  • Откат к нулевой функции, если функция не найдена

    function convertStringtoFunction(functionName){

        var nullFunc = function(){}; // Fallback Null-Function
        var ret = window; // Top level namespace

        // If null/undefined string, then return a Null-Function
        if(functionName==null) return nullFunc;

        // Convert string to function name
        functionName.split('.').forEach(function(key){ ret = ret[key]; });

        // If function name is not available, then return a Null-Function else the actual function
        return (ret==null ? nullFunc : ret);

    }

Использование:


    convertStringtoFunction("level1.midLevel.myFunction")(arg1, arg2, ...);

0 голосов
/ 22 апреля 2014

Это работает для меня:

var command = "Add";
var tempFunction = new Function("Arg1","Arg2", "window." + command + "(Arg1,Arg2)");
tempFunction(x,y);

Я надеюсь, что это работает.

0 голосов
/ 10 марта 2016

Без использования eval('function()') вы можете создать новую функцию, используя new Function(strName). Приведенный ниже код был протестирован с использованием FF, Chrome, IE.

<html>
<body>
<button onclick="test()">Try it</button>
</body>
</html>
<script type="text/javascript">

  function test() {
    try {    
        var fnName = "myFunction()";
        var fn = new Function(fnName);
        fn();
      } catch (err) {
        console.log("error:"+err.message);
      }
  }

  function myFunction() {
    console.log('Executing myFunction()');
  }

</script>
0 голосов
/ 07 сентября 2017

все, что вам нужно сделать, это использовать контекст или определить новый контекст, в котором находятся ваши функции. Вы не ограничены window["f"]();

вот пример того, как я использую некоторые динамические вызовы для некоторых служб REST.

/* 
Author: Hugo Reyes
@ www.teamsrunner.com

*/

    (function ( W, D) { // enclose it as self invoking function to avoid name collisions.


    // to call function1 as string
    // initialize your FunctionHUB as your namespace - context
    // you can use W["functionX"](), if you want to call a function at the window scope.
    var container = new FunctionHUB();


    // call a function1 by name with one parameter.

    container["function1"](' Hugo ');


    // call a function2 by name.
    container["function2"](' Hugo Leon');


    // OO style class
    function FunctionHUB() {

        this.function1 = function (name) {

            console.log('Hi ' + name + ' inside function 1')
        }

        this.function2 = function (name) {

            console.log('Hi' + name + ' inside function 2 ')
        }
    }

})(window, document); // in case you need window context inside your namespace.

Если вы хотите сгенерировать всю функцию из строки, это другой ответ. также обратите внимание, что вы не ограничены одним пространством имен, если ваше пространство имен существует как my.name.space.for.functions.etc.etc.etc последняя ветвь вашего пространства имен содержит функцию как my.name.space.for.functions.etc.etc["function"]();

Надеюсь, это поможет. H.

0 голосов
/ 24 мая 2016
use this

function executeFunctionByName(functionName, context /*, args */) {
      var args = [].slice.call(arguments).splice(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);
    }
0 голосов
/ 16 января 2017

Вы также можете вызвать функцию javascript в eval("functionname as string"). Как показано ниже: (eval - это чистая функция JavaScript)

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

$( document ).ready(function() {

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

Рабочий пример: https://jsfiddle.net/suatatan/24ms0fna/4/

0 голосов
/ 15 ноября 2016

Здесь есть несколько 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...