Nie używaj, eval
chyba ż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);
My.Namespace.functionName()
,this
odniesie się doMy.Namespace
obiektu. Ale kiedy dzwoniszexecuteFunctionByName("My.Namespace.functionName", window)
, nie ma sposobu,this
aby odnieść się do tej samej rzeczy. Może powinien używać przestrzeni nazw jako zakresu lubwindow
jeśli nie ma przestrzeni nazw. Lub możesz zezwolić użytkownikowi na określenie zakresu jako argumentu.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.
źródło
Odpowiedź na to drugie pytanie pokazuje, jak to zrobić: JavaScript odpowiednik locals Pythona ()?
Zasadniczo możesz powiedzieć
lub jak wielu innych sugerowało, możesz po prostu użyć eval:
chociaż jest to wyjątkowo niebezpieczne, chyba że masz absolutną pewność co do tego, co ewaluujesz.
źródło
Czy nie możesz tego po prostu zrobić:
Za pomocą tej metody możesz także wykonać dowolny inny JavaScript.
źródło
eval("My.Namespace.functionName()");
?var codeToExecute = "return My.Namespace.functionName()";
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
Następnie możesz zadzwonić:
Gdzie customFunction będzie ciągiem pasującym do funkcji zdefiniowanej w twoim obiekcie.
źródło
Za pomocą ES6 można uzyskać dostęp do metod klas według nazwy:
wynik byłby:
źródło
Object.create()
. const myObj = {method1 () {console.log ('1')}, method2 () {console.log ('2')}} myObj ['method1'] (); // 1 myObj ['method2'] (); // 2Dwie 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 przezx.y['foo']()
lubx['y']['foo']()
nawetwindow['x']['y']['foo']()
. Możesz łączyć w nieskończoność w ten sposób.źródło
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źródło
Musisz tylko przekonwertować ciąg na wskaźnik o
window[<method name>]
. przykład:a teraz możesz używać go jak wskaźnika.
źródło
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łę:
następnie następująca funkcja:
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:
źródło
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
W zależności od tego, gdzie jesteś, możesz także użyć:
lub, w nodejs
źródło
Jeśli chcesz wywołać funkcję obiektu zamiast funkcji globalnej za pomocą
window["functionName"]
. Możesz to zrobić jak;Przykład:
źródło
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.
źródło
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:
źródło
Zaskoczony, że nie wspomniano o setTimeout.
Aby uruchomić funkcję bez argumentów:
Aby uruchomić funkcję z argumentami:
Aby uruchomić funkcję z głęboką przestrzenią nazw:
źródło
runMe
z kilkoma argumentami.Tak jak inni powiedzieli, zdecydowanie najlepszą opcją jest:
I jak powiedział Jason Bunting , nie zadziała, jeśli nazwa twojej funkcji zawiera obiekt:
Oto moja wersja funkcji, która wykona wszystkie funkcje według nazwy (w tym obiektu lub nie):
źródło
Bardziej rozwiązanie OOP ...
źródło
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ćwindow
na 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.źródło
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ć
this
zamiastwindow
(i pamiętaj: eval is evil :źródło
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.
źródło
Jest też bardzo pomocny sposób.
http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx
źródło
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
onclick
atrybutu i wywołaćclick
metodę.<a href="#" id="link_secret"><!-- invisible --></a>
Lub utwórz
<a>
element w czasie wykonywania.źródło
Najłatwiejszym sposobem jest dostęp do niego tak, jak ma element
jest taki sam jak
źródło
Możesz wywołać funkcję javascript w
eval("functionname as string")
dowolnym z nich. Jak poniżej: (eval jest czystą funkcją javascript)Przykład roboczy: https://jsfiddle.net/suatatan/24ms0fna/4/
źródło
To działa dla mnie:
Mam nadzieję, że to zadziała.
źródło
Nie sądzę, że potrzebujesz skomplikowanych funkcji pośrednich lub eval lub być zależnym od zmiennych globalnych, takich jak window:
Będzie również działał z importowanymi funkcjami:
źródło
Bez użycia
eval('function()')
możesz stworzyć nową funkcję używającnew Function(strName)
. Poniższy kod został przetestowany przy użyciu FF, Chrome, IE.źródło
źródło
Wyglądać podstawowo:
Istniejąca inna funkcja typu to class i look nils petersohn
źródło
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
źródło