Jak zamienić Łańcuch znaków w wywołanie funkcji JavaScript? [duplikat]

To pytanie ma już odpowiedź tutaj:

Mam taki ciąg:

settings.functionName + '(' + t.parentNode.id + ')';

Które chcę przetłumaczyć na wywołanie funkcji Tak:

clickedOnItem(IdofParent);

To oczywiście musi być zrobione w JavaScript. Kiedy robię alert na settings.functionName + '(' + t.parentNode.id + ')'; wydaje się, że wszystko w porządku. Muszę tylko wywołać funkcję, na którą to się przekłada.

Legenda:

settings.functionName = clickedOnItem

t.parentNode.id = IdofParent
Author: Brett DeWoody, 2009-05-27

13 answers

Ponieważ nienawidzę evala i jestem nie sam :

var fn = window[settings.functionName];
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}

Edit: W odpowiedzi na komentarz @ Mahan: W tym konkretnym przypadku {[2] } byłoby "clickedOnItem". To, w czasie wykonywania tłumaczyłoby var fn = window[settings.functionName]; na var fn = window["clickedOnItem"], co uzyskałoby odniesienie do function clickedOnItem (nodeId) {}. Gdy mamy odniesienie do funkcji wewnątrz zmiennej, możemy wywołać tę funkcję przez "wywołanie zmiennej", tzn. fn(t.parentNode.id), co równa się clickedOnItem(t.parentNode.id), czego chciał OP.

Bardziej pełny przykład:

/* Somewhere: */
window.settings = {
  /* [..] Other settings */
  functionName: 'clickedOnItem'
  /* , [..] More settings */
};

/* Later */
function clickedOnItem (nodeId) {
  /* Some cool event handling code here */
}

/* Even later */
var fn = window[settings.functionName]; 
/* note that settings.functionName could also be written
   as window.settings.functionName. In this case, we use the fact that window
   is the implied scope of global variables. */
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}
 334
Author: PatrikAkerstrand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-24 07:39:58
window[settings.functionName](t.parentNode.id);

No need for an eval ()

 67
Author: Fabien Ménager,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 20:37:50

Oto bardziej ogólny sposób, aby zrobić to samo, jednocześnie obsługując zakresy:

// Get function from string, with or without scopes (by Nicolas Gauthier)
window.getFunctionFromString = function(string)
{
    var scope = window;
    var scopeSplit = string.split('.');
    for (i = 0; i < scopeSplit.length - 1; i++)
    {
        scope = scope[scopeSplit[i]];

        if (scope == undefined) return;
    }

    return scope[scopeSplit[scopeSplit.length - 1]];
}
Mam nadzieję, że może pomóc niektórym ludziom.
 64
Author: NGauthier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-28 14:22:13

JavaScript ma eval funkcja oceniająca łańcuch znaków i wykonująca go jako kod:

eval(settings.functionName + '(' + t.parentNode.id + ')');
 15
Author: Andrew Hare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 20:33:10

Eval () jest funkcją, której potrzebujesz, ale radzę spróbować jednej z tych rzeczy, aby zminimalizować użycie eval. Mam nadzieję, że jeden z nich będzie miał dla ciebie sens.

Zapisz funkcję

Przechowuj funkcję jako funkcję, a nie jako ciąg znaków, i używaj jej później jako funkcji. To, gdzie faktycznie przechowujesz tę funkcję, zależy od Ciebie.

var funcForLater = clickedOnItem;

// later is now
funcForLater(t.parentNode.id);

Lub

someObject.funcForLater = clickedOnItem;    
// later is now    
(someObject.funcForLater)(t.parentNode.id);

Store function name

Nawet jeśli musisz zapisać nazwę funkcji jako łańcuch znaków, może zminimalizować złożoność wykonując

(eval(settings.functionName))(t.parentNode.id);

Który minimalizuje ilość Javascript, który musisz skonstruować i eval.

Słownik obsługi

Umieść wszystkie potrzebne funkcje akcji w obiekcie i wywołaj je w stylu słownikowym za pomocą ciągu znaków.

// global
itemActions = { click: clickedOnItem, rightClick: rightClickedOnItem /* etc */ };

// Later...
var actionName = "click"; // Or wherever you got the action name
var actionToDo = itemActions[actionName];
actionToDo(t.parentNode.id);

(mała uwaga: jeśli zamiast tego użyłeś składni itemActions[actionName](t.parentNode.id);, funkcja zostanie wywołana jako metoda itemActions.)

 12
Author: Jesse Millikan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-22 02:34:52

Chociaż podoba mi się pierwsza odpowiedź i nienawidzę evalu, chciałbym dodać, że jest inny sposób (podobny do evalu), więc jeśli możesz go obejść i nie używać, lepiej zrób. Ale w niektórych przypadkach możesz chcieć wywołać kod javascript przed lub po jakimś wywołaniu ajax i jeśli masz ten kod w niestandardowym atrybutie zamiast ajax, możesz użyć tego:

    var executeBefore = $(el).attr("data-execute-before-ajax");
    if (executeBefore != "") {
        var fn = new Function(executeBefore);
        fn();
    }

Lub ewentualnie zapisać to w pamięci podręcznej funkcji, jeśli może być konieczne wywołanie go wiele razy.

Ponownie - nie używaj evala lub tego metoda, jeśli masz inny sposób, aby to zrobić.

 9
Author: nsimeonov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-17 17:21:20

Jeśli settings.functionName jest już funkcją, możesz to zrobić:

settings.functionName(t.parentNode.id);

W przeciwnym razie powinno to również działać, jeśli settings.functionName jest tylko nazwą funkcji:

if (typeof window[settings.functionName] == "function") {
    window[settings.functionName](t.parentNode.id);
}
 7
Author: Gumbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 20:34:54

Chciałem móc przyjąć nazwę funkcji jako ciąg znaków, wywołać ją i przekazać argument do funkcji. Nie mogłem uzyskać wybranej odpowiedzi na to pytanie, ale ta odpowiedź wyjaśniła to dokładnie, a oto krótkie demo.

function test_function(argument)    {
    alert('This function ' + argument); 
}

functionName = 'test_function';

window[functionName]('works!');

To również działa z wieloma argumentami.

 7
Author: B Rad C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:17

Zajęło mi to trochę czasu, aby się tego dowiedzieć, ponieważ konwencjonalne window['someFunctionName']() na początku nie działało dla mnie. Nazwy moich funkcji były wyciągane jako odpowiedź AJAX z bazy danych. Ponadto, z jakiegokolwiek powodu, moje funkcje zostały zadeklarowane poza zakresem okna, więc aby to naprawić, musiałem przepisać funkcje, które wołałem z

function someFunctionName() {}

Do

window.someFunctionName = function() {}
I stamtąd mogłem z łatwością zadzwonić. Mam nadzieję, że to komuś pomoże!
 3
Author: illusivefingers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-26 00:16:07

Na podstawie Nicolasa Gauthiera odpowiedź:

var strng = 'someobj.someCallback';
var data = 'someData';

var func = window;
var funcSplit = strng.split('.');
for(i = 0;i < funcSplit.length;i++){
   //We maybe can check typeof and break the bucle if typeof != function
   func = func[funcSplit[i]];
}
func(data);
 2
Author: Marcos Fernandez Ramos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-09 20:13:35

Wolę używać czegoś takiego:

window.callbackClass['newFunctionName'] = function(data) { console.log(data) };
...
window.callbackClass['newFunctionName'](data);
 1
Author: Tom Johnson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-05 15:29:07

W javascript, który używa specyfikacji CommonJS, jak node.js na przykład możesz zrobić to, co pokażę poniżej. Co jest bardzo przydatne przy dostępie do zmiennej za pomocą ciągu znaków, nawet jeśli nie jest zdefiniowana w obiekcie window. Jeśli istnieje klasa o nazwie MyClass, zdefiniowana w module CommonJS o nazwie MyClass.js

// MyClass.js
var MyClass = function() {
    // I do stuff in here. Probably return an object
    return {
       foo: "bar"
    }
}

module.exports = MyClass;

Możesz zrobić ten miły bit o czary z innego pliku o nazwie MyOtherFile.js

// MyOtherFile.js

var myString = "MyClass";

var MyClass = require('./' + myString);
var obj = new MyClass();

console.log(obj.foo); // returns "bar"

Jeszcze jeden powód, dla którego CommonJS jest taką przyjemnością.

 0
Author: nackjicholson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-29 18:04:30
eval("javascript code");

Jest szeroko stosowany w przypadku JSON .

 -6
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 20:34:07