Как выполнить функцию JavaScript, когда у меня есть ее имя в виде строки

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

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

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

11.12.2008 15:47:10
30 ОТВЕТОВ
РЕШЕНИЕ

Не используйте, 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);
1422
28.08.2018 08:34:07
Вы знаете, что вам не нужна вся конструкция "func"? "context.apply" один хорошо
annakata 11.12.2008 16:36:15
Конечно, я знаю это - но способ, которым я написал функцию, обеспечивает некоторую ясность для тех, кто ее читает, которые могут не полностью понять, что происходит. Я написал эту функцию, понимая, что людям, читающим ее, может понадобиться помощь. Я предоставлю альтернативу, так как вы спросили ...
Jason Bunting 11.12.2008 16:50:49
Поцарапайте это - код достаточно ясен, и те, которые знают, знают. Если вы похожи на меня и знаете, что делаете, вы можете просто внести такие изменения самостоятельно, если использовали этот код. Переполнение стека предназначено для обучения других, и я думаю, что мой код легче понять новичку. Спасибо хоть!
Jason Bunting 11.12.2008 17:21:54
Есть ли ситуация, когда window ["funcName"] будет возвращать undefined? Это проблема, с которой я столкнулся на данный момент. Код вызова и функция определены в двух отдельных файлах js. Я пытался добавить их в тот же файл, но это не имело значения.
codemonkey 16.03.2010 11:19:59
Я думаю, что здесь есть проблема. При звонке My.Namespace.functionName(), thisбудет ссылаться на My.Namespaceобъект. Но когда вы звоните executeFunctionByName("My.Namespace.functionName", window), нет никакого способа thisобратиться к тому же самому. Возможно, ему следует использовать последнее пространство имен в качестве области действия или windowесли нет пространств имен. Или вы можете позволить пользователю указать область действия в качестве аргумента.
JW. 6.07.2011 23:08:42

Ответ на этот другой вопрос покажет вам, как это сделать: эквивалент Javascript для локальных элементов Python ()?

В принципе, вы можете сказать,

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

или, как многие другие предложили, вы можете просто использовать eval:

eval(fname)(arg1, arg2);

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

64
23.05.2017 11:47:29
первая форма намного предпочтительнее
annakata 11.12.2008 15:54:59
Используйте eval только в крайнем случае, когда ничего не помогает.
Jason Bunting 11.12.2008 15:58:18
Это ... но будет ли это работать с такими функциями: xyz (args)?
Kieron 11.12.2008 15:58:57
@keiron: да. см. мой ответ ниже
annakata 11.12.2008 16:02:13

Две вещи:

  • избегайте Eval, это очень опасно и медленно

  • во-вторых, не имеет значения, где ваша функция существует, «глобальность» не имеет значения. x.y.foo()может быть включен через x.y['foo']()или x['y']['foo']()или даже window['x']['y']['foo'](). Вы можете цепляться бесконечно, как это.

24
11.07.2015 11:35:32
но вы не можете использовать window ['xyz'] () для вызова xyz ()
nickf 11.12.2008 16:11:25

Просто подумал, что выложу слегка измененную версию очень полезной функции Джейсона Бантинга .

Во-первых, я упростил первый оператор, указав второй параметр для slice () . Оригинальная версия работала нормально во всех браузерах, кроме IE.

Во- вторых, я заменил это с контекста в обратном заявлении; в противном случае это всегда указывало на окно, когда выполнялась целевая функция.

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);
}
100
23.05.2017 12:02:49
Там нет проверки, чтобы увидеть, если "functionName" на самом деле существует?
Crashalot 2.11.2016 01:08:20
Я думаю, что ответ Mac недооценен. Я не эксперт, но это кажется хорошо продуманным и надежным.
Martin Hansen Lennox 9.03.2017 21:23:37

Вам просто нужно преобразовать вашу строку в указатель window[<method name>]. пример:

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

и теперь вы можете использовать его как указатель.

13
11.11.2011 21:18:40
Это кажется намного более безопасным способом.
James Poulose 23.03.2016 16:20:54

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

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
};
1
23.11.2012 00:38:55

Еще одна деталь на постах Джейсона и Алекса. Я нашел полезным добавить значение по умолчанию в контекст. Просто поставьте context = context == undefined? window:context;в начале функции. Вы можете изменить windowлюбой предпочитаемый контекст, и тогда вам не нужно будет передавать одну и ту же переменную каждый раз, когда вы вызываете ее в контексте по умолчанию.

2
28.12.2012 05:43:30

Если вы хотите вызвать функцию объекта вместо глобальной функции с помощью window["functionName"]. Вы можете сделать это как;

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

Пример:

var now=new Date();
now["getFullYear"]()
9
25.01.2013 13:38:18

Не могли бы вы просто сделать это:

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

Вы также можете выполнить любой другой JavaScript, используя этот метод.

54
16.08.2013 20:56:32
работает, когда с функцией
adeel41 12.09.2014 18:13:56
Как насчет возврата функции?
Peter Denev 31.10.2014 09:08:18
Чем это отличается от eval("My.Namespace.functionName()");?
developerbmw 21.04.2015 00:36:11
@PeterDenev просто измените первую строку наvar codeToExecute = "return My.Namespace.functionName()";
developerbmw 21.04.2015 00:40:30
@developerbmw, вот ответ stackoverflow.com/questions/4599857/…
Tejasvi Hegde 25.10.2016 07:53:06

Все ответы предполагают, что к функциям можно получить доступ через глобальную область видимости (иначе окно). Однако ФП не сделал этого предположения.

Если функции живут в локальной области видимости (или закрытии) и на них не ссылается какой-либо другой локальный объект, неудача: вам нужно использовать eval () AFAIK, смотрите динамический вызов локальной функции в javascript

16
23.05.2017 11:55:10
Чувак (или чувак), большое спасибо за указание на это! Я думал, что схожу с ума на секунду.
Funktr0n 16.03.2014 03:13:37

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

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

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

1
5.10.2017 02:36:24

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

this['fun'+'ctionName']();
1
29.06.2014 16:45:14

БЫТЬ ОСТОРОЖЕН!!!

Следует избегать вызова функции по строке в JavaScript по двум причинам:

Причина 1: некоторые обфускаторы кода разрушают ваш код, поскольку они изменяют имена функций, делая строку недопустимой.

Причина 2: гораздо сложнее поддерживать код, использующий эту методологию, так как гораздо сложнее найти использование методов, вызываемых строкой.

8
20.08.2014 14:21:48

Удивлен, чтобы не упомянуть о 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);
6
17.10.2014 21:39:36
Это не дает ответа на вопрос. Чтобы критиковать или запрашивать разъяснения у автора, оставьте комментарий под его постом - вы всегда можете комментировать свои собственные посты, и, когда у вас будет достаточно репутации, вы сможете комментировать любой пост .
AstroCB 17.10.2014 20:57:32
Пожалуйста, добавьте пример того, как вы бы назвали runMeс несколькими аргументами.
lexicore 17.10.2014 21:01:17
@lexicore Я проголосовал за удаление в очереди на проверку, потому что он не дает четкого ответа на вопрос и сам по себе не имеет особой ценности.
AstroCB 17.10.2014 21:22:47
У этого метода есть потенциально огромный недостаток, поскольку он ставит выполнение в конец очереди рендеринга , что делает этот вызов асинхронным
PeterM 15.11.2016 10:27:41
Мне нравится этот ответ, кажется, работает для моих требований.
Quintonn 18.09.2018 09:27:44

В моем коде очень похожая вещь. У меня есть сгенерированная сервером строка, содержащая имя функции, которое мне нужно передать в качестве обратного вызова для сторонней библиотеки. Итак, у меня есть код, который принимает строку и возвращает «указатель» на функцию, или ноль, если он не найден.

Мое решение было очень похоже на « очень полезную функцию Джейсона Бантинга » * , хотя оно не выполнялось автоматически, и контекст всегда был в окне. Но это можно легко изменить.

Надеюсь, это будет полезно для кого-то.

/**
 * 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;
}
2
23.05.2017 12:02:49

Так что, как говорили другие, определенно лучший вариант:

window['myfunction'](arguments)

И, как сказал Джейсон Бантинг , это не сработает, если имя вашей функции содержит объект:

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

Итак, вот моя версия функции, которая будет выполнять все функции по имени (включая объект или нет):

my = {
    code : {
        is : {
            nice : function(a, b){ alert(a + "," + b); }
        }
    }
};

guy = function(){ alert('awesome'); }

function executeFunctionByName(str, args)
{
    var arr = str.split('.');
    var fn = window[ arr[0] ];
    
    for (var i = 1; i < arr.length; i++)
    { fn = fn[ arr[i] ]; }
    fn.apply(window, args);
}

executeFunctionByName('my.code.is.nice', ['arg1', 'arg2']);
executeFunctionByName('guy');

3
23.05.2017 12:10:47

Я думаю, что элегантный способ сделать это - определить ваши функции в хеш-объекте. Затем вы можете получить ссылку на эти функции из хэша, используя строку. например

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

Тогда вы можете позвонить:

customObject['customFunction'](param);

Где customFunction будет строкой, соответствующей функции, определенной в вашем объекте.

47
2.06.2015 17:13:51
@ibsenv, спасибо за ваш комментарий, чтобы помочь мне определить этот ответ как лучший. Я создал массив объектов функций и, в свою очередь, использовал его для создания массива deferred.promises. Я положил пример кода ниже. (Я не хотел создавать новый ответ и заимствовать ответ Рубена.)
user216661 8.01.2016 16:55:36
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 ();}); вернуть deferred.promise;}); $ q.all (обещания) .then (function (dataArray) {// do stuff})};
user216661 8.01.2016 16:58:15
Это отлично работает, я только добавлю подчеркивание / lodash для проверки, если это функция. А потом беги
elporfirio 21.09.2016 16:18:48

С ES6 вы можете получить доступ к методам класса по имени:

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

результат будет:

1
2
32
8.07.2015 10:22:31
Лучший javascript ЧИСТЫЙ ... Бог ... удалить класс не работает, но все в порядке. Спасибо!
KingRider 3.06.2016 13:51:18
Это то, что я искал от долгого времени. Спасибо!
PaladiN 22.05.2017 12:54:32
ES2015 тут не при чем. Вы можете достичь той же цели, используя чистые объекты или делегирование прототипов через Object.create(). const myObj = {method1 () {console.log ('1')}, method2 () {console.log ('2')}} myObj ['method1'] (); // 1 myObj ['method2'] (); // 2
sminutoli 26.10.2018 02:54:31
Это золото !!! Я удивлен, что никогда не думал об этом раньше. Ницца!!!
thxmike 19.08.2019 01:39:16
Я также считаю, что это самый лучший способ достижения нашей цели.
Chris Jung 5.09.2019 15:50:46

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

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
29.10.2015 12:45:49
Творческое решение, но оно не будет работать для аргументов типа объекта или массива.
Dennis Heiden 11.10.2016 09:42:21
Это использует eval под капотом ... И действительно бьется вокруг куста, чтобы сделать это
Juan Mendes 25.05.2017 21:40:19

Без использования 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
10.03.2016 12:52:39

Самый простой способ получить к нему доступ, как элемент

window.ClientSideValidations.forms.location_form

такой же как

window.ClientSideValidations.forms['location_form']
1
20.04.2016 07:46:47
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
24.05.2016 07:51:29
Почему? Ответы без объяснения, скорее всего, бесполезны.
Daniel W. 11.11.2016 16:49:55

Смотреть основные:

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

0
3.06.2016 14:36:58

Спасибо за очень полезный ответ. Я использую функцию Джейсона Бантинга в своих проектах.

Я расширил его, чтобы использовать его с дополнительным тайм-аутом, потому что обычный способ установить тайм-аут не будет работать. Смотрите вопрос Абхишекиснот

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
	);
    return timeoutID;
}

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

console.log('now wait')
executeFunctionByName("_very._deeply._defined._function", window, 2000, 40, 50 );

0
23.05.2017 12:34:53

Здесь есть несколько 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)
0
15.11.2016 10:44:36

Вы можете вызвать функцию 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/

1
16.01.2017 13:27:12
Это работает хорошо, и это так просто
Carlos E 16.10.2017 16:29:12
И тоже очень медленно.
Marco 1.09.2018 15:11:59

Вот мой вклад в отличные ответы Джейсона Бантинга / Алекса Назарова, где я включаю проверку ошибок, запрошенную 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
  */
12
11.02.2017 01:08:39
Не знаю ... это очень хорошее усилие, это ясно. Но звучит как "слишком широкий" для меня ...
TechNyquist 29.03.2017 09:33:22
А? SO - платформа для вопросов / ответов / обучения. Я с удовольствием приведу все примеры, которые я могу придумать, чтобы, надеюсь, передать освещение. Для меня в этом все дело .
Mac 8.12.2017 18:18:31
Если вы все равно используете функцию functionName, почему бы просто не использовать это?
data 27.09.2018 08:46:50
Это не работает для меня. У меня есть функция пространства имен name abcd, где d это имя функции. вызов executeFunctionByName ("abcd", окно) завершается неудачно в строке, которая проверяет, if( typeof context[ functionName ] !== 'function' )потому что context - window - определен, является объектом и массивом, но window ['abcd'] не существует, поскольку было определено как проблема в принятом ответ: window["My.Namespace.functionName"](arguments); // fail
akousmata 9.05.2019 12:39:02
  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');

Более ООП решение ...

3
27.06.2017 13:52:24

все, что вам нужно сделать, это использовать контекст или определить новый контекст, в котором находятся ваши функции. Вы не ограничены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"]();

Надеюсь, это поможет. ЧАС.

0
7.09.2017 08:06:34

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

  • Работает для функций namespace'd
  • Откат к нулевой функции в случае нулевой / неопределенной строки
  • Откат к нулевой функции, если функция не найдена
    function convertStringtoFunction (functionName) {

        var nullFunc = function () {}; // Резервная нулевая функция
        var ret = window; // Пространство имен верхнего уровня

        // Если ноль / неопределенная строка, то вернуть нулевую функцию
        if (functionName == null) return nullFunc;

        // Преобразовать строку в имя функции
        functionName.split ('.'). forEach (function (key) {ret = ret [key];});

        // Если имя функции недоступно, вернуть Null-функцию, иначе актуальную функцию
        return (ret == null? nullFunc: ret);

    }

Применение:

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

0
2.06.2018 16:09:59