Jak wykonać funkcję JavaScript, gdy mam jej nazwę jako ciąg

1050

Mam nazwę funkcji w JavaScript jako ciąg znaków. Jak przekonwertować to na wskaźnik funkcji, aby móc go później wywołać?

W zależności od okoliczności może być konieczne przekazanie różnych argumentów do metody.

Niektóre funkcje mogą mieć postać namespace.namespace.function(args[...]).

Kieron
źródło

Odpowiedzi:

1438

Nie używaj, evalchyba że absolutnie, pozytywnie nie masz innego wyboru.

Jak już wspomniano, najlepszym sposobem jest użycie czegoś takiego:

window["functionName"](arguments);

To jednak nie będzie działać z funkcją przestrzeni nazw:

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

Oto jak to zrobiłbyś:

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

Aby to ułatwić i zapewnić pewną elastyczność, oto funkcja wygody:

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

Nazwałbyś to tak:

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

Uwaga: możesz przekazać w dowolnym kontekście, więc zrobiłbyś to samo co powyżej:

executeFunctionByName("Namespace.functionName", My, arguments);
Jason Bunting
źródło
4
wiesz, że nie potrzebujesz całej konstrukcji „func”? Sama
opcja
16
Jasne, wiem o tym - ale sposób, w jaki napisałem tę funkcję, zapewnia czytelnikom pewną jasność, która może nie do końca rozumieć, co się dzieje. Napisałem tę funkcję, zdając sobie sprawę, że osoby ją czytające mogą potrzebować pomocy. Podam jednak alternatywę, ponieważ poprosiłeś ...
Jason Bunting,
108
Zdrap to - kod jest wystarczająco przejrzysty, a ci, którzy wiedzą, wiedzą. Jeśli jesteś podobny do mnie i wiesz, co robisz, możesz po prostu wprowadzić takie zmiany, jeśli używałeś tego kodu. Przepełnienie stosu służy edukacji innych i myślę, że mój kod jest łatwiejszy do zrozumienia dla początkującego. W każdym razie dzięki!
Jason Bunting,
4
Czy zdarza się, że okno [„funcName”] zwróci niezdefiniowane? Właśnie w tym momencie mam problem. Kod wywołujący i funkcja są zdefiniowane w dwóch osobnych plikach js. Próbowałem dodać je do tego samego pliku, ale to nie miało znaczenia.
klucz kodowy
5
Myślę, że jest tu problem. Kiedy zadzwonisz My.Namespace.functionName(), thisodniesie się do My.Namespaceobiektu. Ale kiedy dzwonisz executeFunctionByName("My.Namespace.functionName", window), nie ma sposobu, thisaby odnieść się do tej samej rzeczy. Może powinien używać przestrzeni nazw jako zakresu lub windowjeśli nie ma przestrzeni nazw. Lub możesz zezwolić użytkownikowi na określenie zakresu jako argumentu.
JW.
100

Pomyślałem, że opublikuję nieco zmienioną wersję bardzo przydatnej funkcji Jasona Buntinga .

Po pierwsze, uprościłem pierwszą instrukcję, podając drugi parametr do slice () . Oryginalna wersja działała poprawnie we wszystkich przeglądarkach oprócz IE.

Po drugie, mam zastąpić to z kontekstu w instrukcji return; w przeciwnym razie, to zawsze wskazując na okna , gdy funkcja docelowa była wykonywana.

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);
}
Alex Nazarov
źródło
Nie ma możliwości sprawdzenia, czy „nazwa_funkcji” faktycznie istnieje?
Crashalot,
Myślę, że odpowiedź Maca jest niedoceniana. Nie jestem ekspertem, ale wydaje się dobrze przemyślany i solidny.
Martin Hansen Lennox,
65

Odpowiedź na to drugie pytanie pokazuje, jak to zrobić: JavaScript odpowiednik locals Pythona ()?

Zasadniczo możesz powiedzieć

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

lub jak wielu innych sugerowało, możesz po prostu użyć eval:

eval(fname)(arg1, arg2);

chociaż jest to wyjątkowo niebezpieczne, chyba że masz absolutną pewność co do tego, co ewaluujesz.

Eli Courtwright
źródło
6
pierwsza forma jest zdecydowanie lepsza
annakata
19
Używaj eval jako ostateczności, gdy wszystko inne zawiedzie.
Jason Bunting,
1
Jest ... ale czy będzie działał z takimi funkcjami: xyz (args)?
Kieron,
@keiron: tak. patrz moja odpowiedź poniżej
annakata,
55

Czy nie możesz tego po prostu zrobić:

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

Za pomocą tej metody możesz także wykonać dowolny inny JavaScript.

Coley
źródło
3
działa, gdy parzyste argumenty są przekazywane z funkcją
adeel41
Co ze zwrotem funkcji?
Peter Denev
12
Czym to się różni eval("My.Namespace.functionName()");?
developerbmw
@PeterDenev wystarczy zmienić pierwszą linię navar codeToExecute = "return My.Namespace.functionName()";
developerbmw
2
@developerbmw, oto odpowiedź stackoverflow.com/questions/4599857/…
Tejasvi Hegde,
48

Myślę, że eleganckim sposobem na zrobienie tego jest zdefiniowanie swoich funkcji w obiekcie mieszającym. Następnie możesz mieć odwołanie do tych funkcji z skrótu za pomocą łańcucha. na przykład

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

Następnie możesz zadzwonić:

customObject['customFunction'](param);

Gdzie customFunction będzie ciągiem pasującym do funkcji zdefiniowanej w twoim obiekcie.

Ruben Daddario
źródło
@ibsenv, dziękuję za komentarz, który pomógł mi zidentyfikować tę odpowiedź jako najlepszą. Stworzyłem tablicę obiektów funkcyjnych i z kolei wykorzystałem ją do stworzenia tablicy deferred.promises. Poniżej podaję przykładowy kod. (Nie chciałem tworzyć nowej odpowiedzi i pożyczać odpowiedzi Rubena.)
user216661
funkcja getMyData (arrayOfObjectsWithIds) {var functionArray = arrayOfObjectsWithIds.map (funkcja (wartość) {return {myGetDataFunction: MyService.getMyData (value.id)};}) var obiecuje = functionArray.map (funkcja (getDataFunction) {varer q.defer (); getDataFunction.myGetDataFunction.success (function (data) {deferred.resolve (data)}). error (function (error) {deferred.reject ();}); return deferred.promise;}); $ q.all (obiecuje) .then (function (dataArray) {// do stuff})};
user216661
Działa to doskonale. Dodaję tylko podkreślenie / lodash, aby sprawdzić, czy jest to funkcja. A potem biegnij
elporfirio
34

Za pomocą ES6 można uzyskać dostęp do metod klas według nazwy:

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

wynik byłby:

1
2
Nils Petersohn
źródło
1
Najlepszy javascript PURE ... Boże .. usuń klasę nie działa i jest w porządku. Dzięki!
KingRider
1
Tego szukałem od dawna. Dzięki!
PaladiN
ES2015 nie ma tu nic do roboty. Możesz osiągnąć ten sam cel za pomocą czystych obiektów lub delegacji prototypu za pośrednictwem Object.create(). const myObj = {method1 () {console.log ('1')}, method2 () {console.log ('2')}} myObj ['method1'] (); // 1 myObj ['method2'] (); // 2
sminutoli
1
To jest złoto !!! Dziwi mnie, że nigdy o tym nie myślałem. Miły!!!
thxmike,
Myślę też, że jest to najładniejszy sposób na osiągnięcie naszego celu.
Chris Jung
24

Dwie rzeczy:

  • unikaj ewaluacji, jest to strasznie niebezpieczne i powolne

  • po drugie, nie ma znaczenia, gdzie istnieje twoja funkcja, „globalność” nie ma znaczenia. x.y.foo()może być włączony przez x.y['foo']()lub x['y']['foo']()nawet window['x']['y']['foo'](). Możesz łączyć w nieskończoność w ten sposób.

annakata
źródło
1
ale nie możesz zrobić Window ['xyz'] (), aby wywołać xyz ()
nickf
17

Wszystkie odpowiedzi zakładają, że dostęp do funkcji można uzyskać za pomocą zasięgu globalnego (okno). Jednak PO nie przyjął tego założenia.

Jeśli funkcje żyją w zasięgu lokalnym (zwanym także zamknięciem) i nie odwołują się do nich inne obiekty lokalne, pech: Musisz użyć eval()AFAIK, zobacz dynamicznie wywoływanie funkcji lokalnej w javascript

Wolfgang Kuehn
źródło
2
Koleś (lub dudette), dziękuję bardzo za zwrócenie na to uwagi! Przez chwilę myślałem, że wariuję.
Funktr0n
13

Musisz tylko przekonwertować ciąg na wskaźnik o window[<method name>]. przykład:

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

a teraz możesz używać go jak wskaźnika.

Amirali
źródło
To wydaje się być znacznie bezpieczniejszym sposobem.
James Poulose
12

Oto mój wkład w doskonałe odpowiedzi Jasona Buntinga / Alexa Nazarova, w których uwzględniam sprawdzanie błędów wymagane przez Crashalota.

Biorąc pod uwagę tę (wymyśloną) preambułę:

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(){};

następnie następująca funkcja:

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

pozwoli na wywołanie funkcji javascript według nazwy przechowywanej w ciągu znaków, z przestrzenią nazw lub globalną, z argumentami lub bez (w tym obiektów Array), dostarczając informacji zwrotnych na temat napotkanych błędów (mam nadzieję, że je przechwycą).

Przykładowe dane wyjściowe pokazują, jak to działa:

// 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
  */
Prochowiec
źródło
Nie wiem ... to bardzo dobry wysiłek, to jasne. Ale dla mnie brzmi to jak „zbyt szerokie” ...
TechNyquist
2
Co? SO to platforma pytań / odpowiedzi / nauczania. Z przyjemnością przedstawię wszystkie przykłady, które mogę wymyślić, aby przekazać światło. Dla mnie o to chodzi .
Mac
Jeśli mimo to ewaluujesz funkcjęNazwa, dlaczego po prostu jej nie użyć?
dane
To mi nie działa. Mam funkcję przestrzeni nazw abcd, gdzie d jest nazwą funkcji. wywołanie executeFunctionByName („abcd”, okno) kończy się niepowodzeniem w linii, która sprawdza, if( typeof context[ functionName ] !== 'function' )ponieważ kontekst - okno - jest zdefiniowany, jest obiektem i tablicą, ale okno [„abcd”] nie istnieje, ponieważ zostało zidentyfikowane jako problem w zaakceptowanym odpowiedź: window["My.Namespace.functionName"](arguments); // fail
akousmata,
12

W zależności od tego, gdzie jesteś, możesz także użyć:

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

lub, w nodejs

global["funcname"]()
Zibri
źródło
9

Jeśli chcesz wywołać funkcję obiektu zamiast funkcji globalnej za pomocą window["functionName"]. Możesz to zrobić jak;

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

Przykład:

var now=new Date();
now["getFullYear"]()
Ahmet DAL
źródło
8

BĄDŹ OSTROŻNY!!!

Należy starać się unikać wywoływania funkcji przez ciąg znaków w JavaScript z dwóch powodów:

Powód 1: Niektóre zaciemniacze kodu zniszczą Twój kod, ponieważ zmienią nazwy funkcji, powodując, że łańcuch będzie nieprawidłowy.

Powód 2: Znacznie trudniej jest utrzymać kod korzystający z tej metodologii, ponieważ znacznie trudniej jest zlokalizować użycie metod wywoływanych przez ciąg.

dykstrad
źródło
7

Oto moje podejście Es6, które pozwala na wywoływanie funkcji po nazwie jako ciągu lub nazwie funkcji, a także umożliwia przekazywanie różnych liczb argumentów do różnych typów funkcji:

function fnCall(fn, ...args)
{
  let 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"); // should raise an error in console

pouyan
źródło
6

Zaskoczony, że nie wspomniano o setTimeout.

Aby uruchomić funkcję bez argumentów:

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

Aby uruchomić funkcję z argumentami:

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

Aby uruchomić funkcję z głęboką przestrzenią nazw:

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);
abhishekisnot
źródło
To nie daje odpowiedzi na pytanie. Aby skrytykować lub poprosić autora o wyjaśnienie, zostaw komentarz pod jego postem - zawsze możesz komentować własne posty, a gdy będziesz mieć wystarczającą reputację , będziesz mógł komentować każdy post .
AstroCB
Dodaj przykład, jak byś zadzwonił, runMez kilkoma argumentami.
leksykon
1
@lexicore Głosowałem za usunięciem w kolejce recenzji, ponieważ nie zawiera ona wyraźnej odpowiedzi na pytanie i sama w sobie ma niewielką wartość.
AstroCB
1
Ta metoda ma potencjalnie ogromną wadę, ponieważ powoduje zakończenie wykonywania kolejki renderowania , co powoduje, że to wywołanie jest asynchroniczne
PeterM
1
Podoba mi się ta odpowiedź, wydaje się, że działa na moje wymagania.
Quintonn,
3

Tak jak inni powiedzieli, zdecydowanie najlepszą opcją jest:

window['myfunction'](arguments)

I jak powiedział Jason Bunting , nie zadziała, jeśli nazwa twojej funkcji zawiera obiekt:

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

Oto moja wersja funkcji, która wykona wszystkie funkcje według nazwy (w tym obiektu lub nie):

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');

pmrotule
źródło
3
  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');

Bardziej rozwiązanie OOP ...

Leo Lanese
źródło
2

Jeszcze jeden szczegół na temat postów Jasona i Alexa. Przydało mi się dodanie wartości domyślnej do kontekstu. Wystarczy umieścić context = context == undefined? window:context;na początku funkcji. Możesz zmienić windowna dowolny preferowany kontekst, a wtedy nie będziesz musiał przekazywać tej samej zmiennej za każdym razem, gdy wywołasz ją w domyślnym kontekście.

Bradley Shrader
źródło
2

Aby dodać do odpowiedzi Jasona Buntinga, jeśli używasz nodejs lub czegoś (i to działa również w dom js), możesz użyć thiszamiast window(i pamiętaj: eval is evil :

this['fun'+'ctionName']();
Cilan
źródło
2

W moim kodzie jest bardzo podobna rzecz. Mam ciąg wygenerowany przez serwer, który zawiera nazwę funkcji, którą muszę przekazać jako wywołanie zwrotne dla biblioteki innej firmy. Mam więc kod, który pobiera ciąg znaków i zwraca „wskaźnik” do funkcji, lub null, jeśli go nie znaleziono.

Moje rozwiązanie było bardzo podobne do „ bardzo przydatnej funkcji Jasona Buntinga* , chociaż nie wykonuje się ono automatycznie, a kontekst jest zawsze wyświetlany w oknie. Ale można to łatwo zmienić.

Mam nadzieję, że będzie to komuś pomocne.

/**
 * 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;
}
Nomaed
źródło
1

Nie mogę się oprzeć wspominaniu o innej sztuczce, która pomaga, jeśli masz nieznaną liczbę argumentów, które są również przekazywane jako część ciągu zawierającego nazwę funkcji. Na przykład:

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

Jeśli JavaScript działa na stronie HTML, wszystko czego potrzebujesz to niewidoczny link; możesz przekazać ciąg do onclickatrybutu i wywołać clickmetodę.

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

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

Lub utwórz <a>element w czasie wykonywania.

Magnus Smith
źródło
Kreatywne rozwiązanie, ale to nie zadziała w przypadku argumentów typu obiektowego lub tablicowego.
Dennis Heiden,
1
Wykorzystuje eval pod maską ... I naprawdę kręci się wokół buszu, aby to zrobić
Juan Mendes
1

Najłatwiejszym sposobem jest dostęp do niego tak, jak ma element

window.ClientSideValidations.forms.location_form

jest taki sam jak

window.ClientSideValidations.forms['location_form']
crazycrv
źródło
1

Możesz wywołać funkcję javascript w eval("functionname as string")dowolnym z nich. Jak poniżej: (eval jest czystą funkcją javascript)

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

$( document ).ready(function() {

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

Przykład roboczy: https://jsfiddle.net/suatatan/24ms0fna/4/

Dr Suat Atan
źródło
To działa dobrze i jest takie proste
Carlos E
1
A także bardzo wolno.
Marco
1

To działa dla mnie:

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

Mam nadzieję, że to zadziała.

DevAshish
źródło
1

Nie sądzę, że potrzebujesz skomplikowanych funkcji pośrednich lub eval lub być zależnym od zmiennych globalnych, takich jak window:

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

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

const operations = {
  fun1,
  fun2
};

let temp = "fun1";

try {
  // You have to use square brackets property access
  operations["fun1"]("Hello World");
  operations["fun2"]("Hello World");
  // You can use variables
  operations[temp]("Hello World");
} catch (error) {
  console.error(error);
}

Będzie również działał z importowanymi funkcjami:

// 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
};

try {
  operations["fun1"]("Hello World");
  operations["fun2"]("Hello World");
} catch (error) {
  console.error(error);
}
SnnSnn
źródło
0

Bez użycia eval('function()')możesz stworzyć nową funkcję używając new Function(strName). Poniższy kod został przetestowany przy użyciu 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>
Ithar
źródło
0
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);
    }
Pratik
źródło
1
Dlaczego? Odpowiedzi bez wyjaśnień są najprawdopodobniej bezużyteczne.
Daniel W.
0

Wyglądać podstawowo:

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

Istniejąca inna funkcja typu to class i look nils petersohn

KingRider
źródło
0

Dzięki za bardzo pomocną odpowiedź. Korzystam z funkcji Jasona Buntinga w moich projektach.

Rozszerzyłem go, aby używał go z opcjonalnym limitem czasu, ponieważ normalny sposób ustawienia limitu czasu nie zadziała. Zobacz pytanie abhishekisnota

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 );

Neo
źródło