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

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

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

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

Ответы [ 32 ]

9 голосов
/ 25 января 2013

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

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

Пример:

var now=new Date();
now["getFullYear"]()
8 голосов
/ 20 августа 2014

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

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

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

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

6 голосов
/ 18 октября 2014

Удивлен, что не упомянул 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 октября 2018

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

function fnCall(fn, ...args)
{
  let func = (typeof fn =="string")?window[fn]:fn;
  if (typeof func == "function") func(...args)
  else console.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"); // should raise an error in console
5 голосов
/ 26 февраля 2019

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

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

или, в nodejs

global["funcname"]()
3 голосов
/ 27 июня 2017
  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 голосов
/ 22 мая 2015

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

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');
2 голосов
/ 28 декабря 2012

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

2 голосов
/ 29 апреля 2015

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

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

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

/**
 * 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;
}
1 голос
/ 20 апреля 2016

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

window.ClientSideValidations.forms.location_form

совпадает с

window.ClientSideValidations.forms['location_form']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...