2012-02-10 13 views
5

W PHP można użyć ciągów do dynamicznego wybierania klasy do tworzenia instancji. Oto 2 prostych klas w PHP:Nowa instancja obiektu JavaScript z dynamiczną nazwą funkcji

<?php 
class Magic implements Genius { 
    public function perform() { 
    echo 'madya look :P' . PHP_EOL; 
    } 
} 

class Genie implements Genius { 
    public function perform() { 
    echo 'your wish has been granted!' . PHP_EOL; 
    } 
} 

Teraz nie może być zmienną takie, że klasa instancji w czasie wykonywania opiera się na jego zawartość

$sGeniusClass = 'Magic'; 
$oGenius  = new $sGeniusClass(); 

Teraz w JavaScripcie lubię używać funkcje jak konstruktorów mieć pewien poziom wpisany-ności, w tym duchu może mam:

function Magic() {} 
Magic.prototype = { 
    perform : function() 
    { 
    console.log('madya look :P'); 
    } 
} 

function Genie() {} 
Genie.prototype = { 
    perform : function() 
    { 
    console.log('your wish has been granted!'); 
    } 
} 

wiem, że mogę zdjąć coś podobnego do PHP z eval:

podejście # 1

var sClassName = 'Genie'; 
eval('var oGenius = new ' + sClassName); 

Ja również widziałem an approach sprawia, że ​​połączenia do Function funkcję:

Podejście # 2

var sClassName = 'Genie'; 
var oGenius = new Function('return new ' + sClassName)(); 

On the MDN choć brzmi tak cierpi wydajność z ponownej oceny za każdym razem instancją jest Utworzono:

obiekty funkcyjne utworzone z konstruktora Function są przetwarzane, gdy funkcja jest tworzony. Jest to mniej efektywne niż deklarowanie funkcji i wywoływanie jej w kodzie, ponieważ funkcje deklarowane jako za pomocą instrukcji function są analizowane z resztą kodu.

Teraz mam jeszcze jedno podejście, które jest nieco uciążliwe:

Podejście # 3

var aClassMap = { 
    Magic : Magic, 
    Genie : Genie, 
    create : function(sClassName) { 
    if(this[sClassName] === undefined) 
     return false; 
    return new this[sClassName]; 
    } 
} 

var sClassName = 'Genie'; 
var oGenius = aClassMap.create(sClassName); 

Wydaje się, że mój ulubiony ogólnie rzecz biorąc, nie ma sensu z eval i bez późniejszej ponownej oceny, np. rozwiązanie nr 2. Jest jeszcze trochę pracy jednak, więc moje pytanie, dwojakie:

  1. Czy są jakieś inne sposoby, aby to zrobić inny niż 3 podejścia, jakie pokazane?
  2. Czy jest coś podobnego do PHP, w którym ciąg może odwzorować funkcję, która ma być utworzona?
+0

Jak zastosować podejście nr 2 z przekazywaniem argumentów do nowej funkcji? Zostanie wykonana w następujący sposób: 'new Genie ('foo')' Z 'foo' również będącym zmienną? –

+0

Znaleziono! To wygląda następująco: 'var oGenius = nowa funkcja ('arg1', 'return new' + sClassName + '(arg1)') ($ argumentVariable);' –

Odpowiedz

4

Myślę, że pokryłeś je wszystkie. Można uprościć 3rd podejście jednak, by pamiętać, że zmienne i funkcje globalne są właściwości obiektu okna, dzięki czemu można tworzyć globalne zajęcia z wykorzystaniem window coś takiego:

var myClassName = "Genie"; 
window[myClassName] = function {}; 
window[myClassName].prototype = { 
    perform : function() 
    { 
    console.log('I am a ' + myClassName + ', and your wish has been granted!'); 
    } 
} 

myślę wydajność będzie tak dobry jak zawsze (ponieważ JavaScript używa tabel mieszających wewnętrznie do odniesienia właściwości obiektu, bez względu na wszystko).

+0

Zdecydowanie wygląda na rozsądne podejście z jedyną wadą: nie przenoś się do innych środowisk, takich jak _node.js_. Jednak nie wspomniałem o tym w pytaniu :) – quickshiftin

+0

Nie musisz tak naprawdę modyfikować sposobu deklarowania typów. Nadal możesz po prostu napisać funkcję Genie() {}, a następnie utworzyć instancję z var o = new window ["Genie"](); – SynXsiS

+0

Ah @SynXsiS, to świetna wskazówka i najczystsza rzecz, jaką widziałem, thx. – quickshiftin

Powiązane problemy