2012-03-20 20 views
6

Czy istnieje sposób na uzyskanie zmiennej nazwa, jak można zrobić w .Net z refleksji?
jak w tym scenariuszu:Uzyskaj nazwę zmiennej. javascript "reflection"

function(x,y,z) 
{ 
    if (x === 0) 
     logger.log('variable ' + x.reflectedName ' has invalid value ' + x) 
     // logs: 'variable x has invalid value 0) 
    ... 
} 

Znalazłem podobne pytania, które chciały nazwę var poza funkcją (?!), ale nie mógł znaleźć na to pytanie.

(jQuery jest opcja, choć nie mogę myśleć, jak można to zrobić z nim ...)

+7

Warto zwrócić uwagę: nie można uzyskać nazwy zmiennej poprzez odbicie w .NET. – StriplingWarrior

+0

@StriplingWarrior. możesz z 'Expression' uprościć go dla żadnego deweloperów .Net ... – gdoron

+1

dlaczego nie po prostu zapisać nazwy zmiennej w ciągu znaków? w twoim przykładzie równie łatwo byłoby umieścić x w ciągu 'console.log ('zmienna x ma nieprawidłową wartość:', x)' – SpYk3HH

Odpowiedz

7

Ponieważ używasz .NET jako przykład, załóżmy, że na chwilę zagłębić. W C#, można utworzyć funkcję, która bierze Expression:

void BadArgument<T>(Expression<Func<T>> argExpr) 
{ 
} 

Jednak aby móc wyodrębnić nazwę zmiennej z wywołania tej funkcji, trzeba by upewnić się, że rozmowa zawsze używa dokładnie prawo składni (chociaż nie ma sposobu, aby egzekwować to w czasie kompilacji):

if(x < 0) 
    BadArgument(() => x); 

Więc można to zrobić, ale to jest bardzo delikatne i bardzo powolny. Generalnie generujesz instrukcje, aby utworzyć całe drzewo wyrażeń oparte na wyrażeniu lambda () => x, więc funkcja, którą wywołujesz, może przeanalizować to drzewo wyrażeń i spróbować znaleźć nazwę argumentu.

Czy można tego dokonać w javascript? Pewnie!

w JavaScript, zamknięcia są wytwarzane poprzez funkcje wewnętrzne, więc odpowiednikiem powyższego wyrażenia lambda byłoby:

function(){return x;} 

A ponieważ JavaScript jest językiem skryptowym, każda funkcja jest równoznaczne z jego własnej definicji jako ciąg. Innymi słowy, nazywając .toString() na powyższej funkcji przyniesie:

function(){return x;} 

This jsfiddle shows jak można wykorzystać to w funkcji rejestrowania stylu. Następnie możesz parsować wynikowy ciąg funkcyjny, który będzie tylko trochę bardziej kłopotliwy niż analizowanie drzewa .NET Expression. Ponadto uzyskanie rzeczywistej wartości o wartości z x jest jeszcze łatwiejsze niż w .NET: po prostu call the function!

Ale tylko dlatego, że może robią to nie znaczy, że powinien. Miło jako gee-whiz salonu podstęp, ale gdy przychodzi co do czego, to nie warto:

  • To kruche: co jeśli jakiś deweloper nie używać go w prawo i daje funkcję nie możesz parsować?
  • Nie działa w przypadku zminimalizowania: wyobraź sobie otrzymanie komunikatu, że zmienna a ma niepoprawną wartość, ponieważ minifunkcjonowana funkcja zmieniła nazwy zmiennych.
  • Dodaje narzut: nawet minifier nie może skrócić function(){return x;}, aby być mniejszym niż "x".
  • Wreszcie, jest to skomplikowane. - powiedział nuff.
+0

** Doskonale! ** Nie będę go używać zgodnie z sugestią, ale jest to doskonała odpowiedź ! BTW jakiego wyrażenia regularnego użyłbyś, aby uzyskać 'x' z' function() {return x;} '? – gdoron

+1

@gdoron: Nie wiem, czy użyłbym regex, czy nie. Zasadniczo po prostu chcesz wziąć wszystko po "powrocie" i przed "}", i usunąć wszelkie spacje lub średniki, i powiedzieć krótką modlitwę, że kod wywołujący nie rzucił ci krzywej piłki. – StriplingWarrior

+0

** Uwaga! ** zachowaj ostrożność przy 'zaminowaniu', kiedy _minminuj_ twoja nazwa pliku * .js może zmienić nazwę. @gdoron –

6

Nie możesz. Ale skoro już znasz nazwę zmiennej (ponieważ musisz ją użyć, aby połączyć ją z końcem ciągu znaków), dlaczego nie po prostu ją wpisać?

tj .:

logger.log('variable x has invalid value '+x); 
+3

Myślę, że przykład był dla prostoty. Zakładam, że OP chce to zrobić w przypadkach, gdy nazwa zmiennej nie jest znana z góry. Ale +1 dla "Nie możesz". –

+0

Co jeśli ktoś wywoła funkcję z własnymi zmiennymi: 'function (a, b, c)', 'x' będzie dla nich bez znaczenia. –

+0

Wiem, że mogę hardcode 'x' ale nie chcę tot z własnych powodów ... – gdoron

6

W rzeczywistości jesteś CAN. Oto przykładowy numer:

function getVarName(v) { 
    for (var key in window) { 
     if (window[key] === v) 
      return key; 
    } 
} 
var testvar = 13142; 
function test(t) { 
    var varName = getVarName(t); 
    // window[varName] -- your variable actualy 
    alert(varName); 
} 
test(testvar); // testvar 

Innym problemem jest utworzenie niektórych zmiennych, które zawierają tę samą zmienną. Wtedy pierwszy var zostanie zwrócony.

+5

'var testvar = 13142; var testvar2 = 13142;' lub 'var testvar = true;' lub cokolwiek, co jest obiektem, zrujnuje twój dzień. Wszystko, co nie jest zdefiniowane w globalnym zasięgu systemu Windows, również zrujnuje Twój dzień. –

-1

Łatwo jest dostać nazwę zmiennej

//This is variable you want to get the name 
var prop; 

var obj = {prop}; 
for(var propName in obj){ 
    alert(propName); 
    break; 
} 

również można spróbować w .

+0

Nie sądzę, że masz pytanie. Przeczytaj ponownie inne odpowiedzi lub pytanie. Dzięki, niezależnie – gdoron