2012-10-18 16 views
8

Podając ciąg znaków classname, chcę dynamicznie utworzyć nową funkcję JavaScript o nazwie następującej po tym ciągu znaków, która może być używana do tworzenia instancji obiektów.Utwórz funkcję JavaScript dynamicznie z nazwy ciągu znaków

Próbowałem już używać eval(), ale z jakiegoś powodu zadeklarowana funkcja nie pojawia się w zasięgu globalnym (okno).

eval("function " + classname + "() {}"); 
window[ classname ]; // => undefined 

Czy istnieje sposób, w jaki mogę dynamicznie utworzyć nową funkcję o nazwie po ciągu?

Lub alternatywnie, daj mi jakiś sposób, aby odwołać się do utworzonej funkcji po utworzeniu jej przez eval. Co ciekawe, pojawia się jako zmienna lokalna podczas debugowania jej w Safari.

Aktualizacja:

Got it! Oczywiście to oczywiste, wystarczy użyć eval ponownie utworzyć instancję:

var myInstance = eval("new " + classname); 
myInstance.constructor.name; // => classname (yay) 

To powinno działać w moim przypadku, bo wystarczy, aby utworzyć jedną instancję klasy po prawej to zadeklarowana. W ogólnym przypadku zobacz odpowiedź Pointy.

+0

prawda moim jedynym prawdziwym powodem, dla którego chcę to zrobić, jest to, że obiekty pojawiają się jako "classname" w debugerze. :) – devios1

Odpowiedz

9

Tak:

window[classname] = function() { ... }; 

Teraz, w uczciwości, to nie dokładnie jak co próbowali, ale to dość blisko. Gdy tworzysz funkcję za pomocą tego wyrażenia i nie posiadając nazwy, funkcja nie może się odnosić do siebie, chyba że przez nazwę w zewnętrznym zasięgu (w tym przypadku zasięg globalny).

Jeśli to ważne, co można zrobić, to w ten sposób: utworzyć funkcję z jakimś magazynie „wewnętrznego” nazwy, a następnie przypisać ją do nazwy globalnej:

function secretName() { ... } 

window[classname] = secretName; 
+2

Tak, naprawdę chciałbym, aby funkcja była poprawnie nazwana. – devios1

+0

Udzielenie tej odpowiedzi, ponieważ jest to najbardziej elegancki sposób, nie licząc mojego irracjonalnego pragnienia, aby obiekt był nazwaną funkcją. – devios1

+0

@chaiguy Cóż, po prostu musisz zdecydować, czy posiadanie funkcji "właściwej" nazwy wewnętrznej jest warte nieprzyjemności używania 'eval()', gdy istnieje dość dobra alternatywa. – Pointy

2

Spróbuj:

var classname = "myFunction"; 

window[ classname ] = function() {}; 

alert(window[ classname ]); // => undefined 
6

Chociaż jest to w zasadzie takie samo, jak eval(), ale zarejestruje funkcję w domenie bieżącej strony. Możesz później usunąć ten element skryptu lub użyć go ponownie do innych funkcji.

+0

Interesujące podejście, dzięki za pomysł. – devios1

+0

Jest to inne podejście. Wydaje mi się, że działa mi dobrze. – Vikneshwar

1

W przypadku, gdy nie chcemy tworzyć nowe funkcje oparte na jakimś ciągiem, ale na podstawie innej podobnej funkcji: (to nie może być dobrym przykładem, ale nadzieję, że może masz pomysł)

function createListOfFunctions(functionNameList) { 
    resultFunctions = {}; 

    // Loop all names to create a list of functions with those names 
    $.each(functionNameList, function(index, functionName) { 
    resultFunctions[functionName] = _createFunction(functionName); 
    }); 

    return resultFunctions; 
} 

function _createFunction(name) { 
    return function(anotherNameToCompare) { 
    // customize this funciton whatever you like 
    return name == anotherNameToCompare; 
    }; 
} 


// USAGE: 
functionNameList = ['stack', 'overflow']; 
result = createListOfFunctions(functionNameList); // result = { stack: function(name) {...}, overflow: function(name) {...} } 

result.stack('stack'); // true 
result.stack('not stack'); // false 
result.overflow('overflow'); // true 
Powiązane problemy