Nazwa zmiennej jako ciąg znaków w JavaScript

154

Czy istnieje sposób, aby uzyskać nazwę zmiennej jako ciąg znaków w JavaScript? (jak NSStringFromSelectorw kakao )

Chciałbym zrobić tak:

var myFirstName = 'John';
alert(variablesName(myFirstName) + ":" + myFirstName);

--> myFirstName:John

AKTUALIZACJA

Próbuję połączyć przeglądarkę i inny program za pomocą JavaScript. Chciałbym wysłać nazwy instancji z przeglądarki do innego programu dla metody wywołania zwrotnego:

FooClass = function(){};
FooClass.someMethod = function(json) {
  // Do something
}

instanceA = new FooClass();
instanceB = new FooClass();
doSomethingInAnotherProcess(instanceB); // result will be substituted by using instanceB.someMethod();

...

Z innego programu:

evaluateJavascriptInBrowser("(instanceName).someMethod("resultA");");

W PHP: Jak uzyskać nazwę zmiennej jako ciąg znaków w PHP?

ziemniak rybny
źródło
2
@delnan Rzeczywiście, +1. Nie przychodzi mi do głowy inny sposób ujęcia tego niż „jeśli potrafisz pisać variablesName(myFirstName), znasz już nazwę zmiennej”. Próbuję, ale nie mogę ...
zamrozić
1
może w tym celu mógłbyś zapisać w zmiennej i później przekonwertować ją na json, na przykład {"instanceA": instanceA} i wysłać do serwera przy użyciu ajax lub wywołania get / post i że możesz przetworzyć w php i uzyskać nazwę instancji ...
Geomorillo
@deceze, oczywiście, znasz nazwę, ale to nie znaczy, że możesz / chcesz wpisać ją ręcznie. Może chcesz zrzucić kilka zmiennych do celów debugowania i nie masz ochoty ręcznie wpisywać console.log("myvar = " + myvar);w kółko każdej zmiennej.
Synetech

Odpowiedzi:

54

Zwykle użyłbyś tabeli skrótów w sytuacji, w której chcesz zmapować nazwę na jakąś wartość i móc pobrać obie.

var obj = { myFirstName: 'John' };
obj.foo = 'Another name';
for(key in obj)
    console.log(key + ': ' + obj[key]);

karim79
źródło
125
Nie odpowiada jednak na pytanie.
htafoya,
1
@htafoya: Pośrednio, tak - wszystkie właściwości objsą drukowane jako name: valuepary. Ale tekst wyjaśniający mógłby być bardziej przejrzysty.
Matt
1
@Mat Rozumiem kod, ale generalnie pytanie OP jest używane do czegoś bardziej złożonego, jak przypisania dynamiczne, w których można wybrać zmienną z wygenerowanego ciągu. Lub gdzie zwykłe utworzenie słownika do wydrukowania wartości jest przesadą.
htafoya
2
@htafoya - tak, coś prostego jak nameof (varname) w C #.
Matt
1
Myślę, że jedynym powodem, dla którego to „nie odpowiada na pytanie” jest to, że nie zaczyna się od „Nie możesz uzyskać nazwy stałej lub zmiennej w JavaScript. Najbardziej zbliżona do tego, czego chcesz ...”, na przykład ta inna odpowiedź: stackoverflow.com/a/37393679
bigpopakap
86

Podobnie jak odpowiedź Setha, ale Object.keys()zamiast tego używa :

const varToString = varObj => Object.keys(varObj)[0]

const someVar = 42
const displayName = varToString({ someVar })
console.log(displayName)

Pączki
źródło
5
@titusfx możesz zamienić const na let lub var i działa tak samo. Ale jeśli używasz transpilera do niszczenia obiektów w pierwszej kolejności, prawdopodobnie obsługuje on już const.
SethWhite
Wydaje się, że zależy to od używania ES6?
O'Rooney
1
@ O'Rooney Tak, to jest specyficzne dla ES6.
Donuts
63

Aby rozwiązać problem, możesz skorzystać z następującego rozwiązania:

const myFirstName = 'John'
Object.keys({myFirstName})[0]

// returns "myFirstName"
Kolega nieznajomy
źródło
3
Ta odpowiedź jest podobna do [@ SethWhite's] ( stackoverflow.com/a/39669231/5876282 ), ale jest znacznie uproszczona. Dzięki! @bluejayke Myślę, że ta odpowiedź pojawia się wiele lat później po pierwotnie zaakceptowanej odpowiedzi. Ale tak, obecnie jest to najlepsze - może z wyjątkiem użycia „pop ()” sugerowanego poniżej
B Charles H
1
czy można zrobić funkcję, która przyjmie zmienną i wypisze jej nazwę? Próbowałem zawinąć twój kod w funkcję, ale id zwrócił mi nazwę, która została użyta jako argument
Wakan Tanka
@WakanTanka Jeśli utworzysz właściwe pytanie, odpowiem tam.
Fellow Stranger
@WakanTanka nie, to nie zadziała. Jak odkryłeś, po prostu wypisze nazwę, którą podasz argumentowi funkcji. Myślę, że warto zobaczyć, jak taka funkcja skompilowałaby się do starszej specyfikacji Javascript. W tym przykładzie ( jsfiddle.net/bigpopakap/wq891ghr/2 ) widać, że składnia {zmienna} jest po prostu skrótem od {zmienna: zmienna}, więc nie można użyć nazwy zmiennej z funkcji wywołującej
bigpopakap
42

W ES6 można by napisać coś takiego:

let myVar = 'something';
let nameObject = {myVar};
let getVarNameFromObject = (nameObject) => {
  for(let varName in nameObject) {
    return varName;
  }
}
let varName = getVarNameFromObject(nameObject);

Nie najlepiej wyglądająca rzecz, ale spełnia swoje zadanie.

Wykorzystuje to niszczenie obiektów w ES6.

Więcej informacji tutaj: https://hacks.mozilla.org/2015/05/es6-in-depth-destruifying/

SethWhite
źródło
1
Świetna odpowiedź!! To szczególne zastosowanie niszczenia obiektów jest dla mnie nowe (wiersz 2 jest let nameObject = {myVar}bardzo przydatny! Nie wydaje się być nigdzie udokumentowany. Masz jakieś linki?
Laurence Lord
2
@LaurenceLord nazywa się to skrótem właściwości. Przypisanie właściwości obiektu bez definicji (coś: „asdf”) spowoduje, że JS zdefiniuje właściwość z nazwą zmiennej i jej wartością {coś} === {coś: coś}. ariya.io/2013/02/…
SethWhite
19
var x = 2;
for(o in window){ 
   if(window[o] === x){
      alert(o);
   }
}

Jednak myślę, że powinieneś lubić „karim79”

koniczyna
źródło
8
Będzie to działać tylko w zakresie okna (przerwy, gdy wewnątrz funkcji).
jpillora
1
Zgoda - ale najbliżej odpowiedzi na pytanie PO. Gj.
Dembinski
również jeśli testujesz prymityw, zaalarmuje wszystkie zmienne, które mają tę samą wartość lub jeśli dwie zmienne mają przypisany ten sam obiekt. Na przykład, jeśli pierwszym wierszem był x = 2; y = 2;lubx = {a:1}; b = x; ostrzegłaby każdego z nich
aljgom
Jeśli chcesz, aby to działało w zakresie funkcji , możesz spróbować użyć nazwy funkcji zamiast okna, na przykład: var foo = function f(){ f.x = 2; for(o in f){ if(f[o]===f.x) alert(o); } } wtedy wywołanie f()ostrzeże
``
1
@aljgom - dobra uwaga. Tutaj jest skrzypce do wypróbowania.
Matt
16

Działa to w przypadku podstawowych wyrażeń

const nameof = exp => exp.toString().match(/[.](\w+)/)[1];

Przykład

nameof(() => options.displaySize);

Skrawek:

var nameof = function (exp) { return exp.toString().match(/[.](\w+)/)[1]; };
var myFirstName = 'Chuck';
var varname = nameof(function () { return window.myFirstName; });
console.log(varname);

BrunoLM
źródło
2
To działa całkiem nieźle! jedynym problemem jest to, że przekazujesz coś takiego: nameof (() => options.subOptions.displaySize), która zwraca "subOptions" Zamiast tego użyłem tego wyrażenia regularnego: exp.toString (). match (/ (? = [^ .] * $) (\ w +) / g) [0]
Jim Brown
Jestem niezdefiniowany z: var a = {b: "c"}; alert (nazwa (a)); nazwa funkcji (exp) {exp.toString (). match (/ (? = [^.] * $) (\ w +) / g) [0]; } // nazwa
David Spector
@JimBrown, dziękuję! Twój komentarz musi być oznaczony jako odpowiedź!
evorios,
14

Prawdopodobnie pop byłby lepszy niż indeksowanie z [0] ze względów bezpieczeństwa (zmienna może być zerowa).

const myFirstName = 'John'
const variableName = Object.keys({myFirstName}).pop();
console.log(`Variable ${variableName} with value '${variable}'`);

// returns "Variable myFirstName with value 'John'"
Juangui Jordán
źródło
3
Jeśli myFirstName jest przekazywana do funkcji (zawierającej ten kod) jako argument v, wówczas nazwa zmiennej jest raportowana jako v zamiast myFirstName.
David Spector
9
var somefancyvariable = "fancy";
Object.keys({somefancyvariable})[0];

Nie można tego przekształcić w funkcję, ponieważ zwraca nazwę zmiennej funkcji.

// THIS DOESN'T WORK
function getVarName(v) {
    return Object.keys({v})[0];
}
// Returns "v"

Edycja: Podziękowania dla @Madeo za wskazanie, jak uczynić to funkcją .

function debugVar(varObj) {
    var varName = Object.keys(varObj)[0];
    console.log("Var \"" + varName + "\" has a value of \"" + varObj[varName] + "\"");
}

Będziesz musiał wywołać funkcję z pojedynczą tablicą elementów zawierającą zmienną. debugVar({somefancyvariable});
Edycja: Object.keysmożna odwoływać się tak, jak keysw każdej przeglądarce, w której go testowałem, ale zgodnie z komentarzami nie działa wszędzie.

Cadiboo
źródło
Błąd: „Nie można znaleźć kluczy zmiennych”
Alexander Volkov
klucze nie są zdefiniowane
lawina 1
1
powinno być tak, const getVarName = (v) => Object.keys(v)[0];a następnie wywołaj tę funkcję w ten sposóbgetVarName({whatEverVariable})
Madeo
6

Od ECMAScript 5.1 możesz używać Object.keys do pobierania nazw wszystkich właściwości z obiektu.

Oto przykład:

// Get John’s properties (firstName, lastName)
var john = {firstName: 'John', lastName: 'Doe'};
var properties = Object.keys(john);

// Show John’s properties
var message = 'John’s properties are: ' + properties.join(', ');
document.write(message);

Benny Neugebauer
źródło
4

Kiedy funkcja jest zapisywana w funkcji, która zmienia wartości różnych zmiennych globalnych, nie zawsze jest to moje pierwsze imię, lecz jest to coś, przez co przechodzi. Spróbuj, to zadziałało dla mnie.

Uruchom w jsfiddle

var jack = 'jill';
function window_getVarName(what)
{
  for (var name in window)
  {
    if (window[name]==what)
    return(name);
  }
  return("");
}
document.write(window_getVarName(jack));

Napiszę do okna „jack”.

Matt Smith
źródło
2
To nie jest wiarygodne. W obiekcie window może znajdować się dowolna liczba zmiennych o tej samej wartości.
Taylor Buchanan
2

Możesz zastanowić się nad typami w javascript i uzyskać nazwy właściwości i metod, ale to, czego potrzebujesz, to coś takiego jak Lambda Expressions Treesw .NET, myślę, że nie jest to możliwe ze względu na dynamiczny charakter i brak statycznego systemu typów w javascript.

Jahan
źródło
3
Nie sądzę, aby JSowi brakowało lambd lub powiązanych narzędzi programowania funkcjonalnego.
Ale myślę, że nie ma struktury odpowiadającej drzewom wyrażeń w .NET.
Jahan
2

Potrzebowałem tego, nie chcę używać obiektów i wymyśliłem następujące rozwiązanie, odwracając pytanie.

Zamiast zamieniać nazwę zmiennej na ciąg, konwertuję ciąg na zmienną.

Działa to tylko wtedy, gdy znana jest nazwa zmiennej.

Weź to:

var height = 120;
testAlert(height);

Powinno to wyświetlić:

height: 120

Można to zrobić w następujący sposób:

function testAlert(ta)
{
    a = window[ta];
    alert(ta + ': ' + a); 
}

var height = 120;
testAlert("height");
// displays: height: 120

Więc używam ciągu "height"i zamieniam go w zmienną heightza pomocą window[]polecenia.

SPRBRN
źródło
2
W drugim przypadku wysokość jest właściwością windowobiektu, ponieważ zmienna o tej samej nazwie została zadeklarowana w zakresie okna. Działa to tylko wtedy, gdy zmienna jest zadeklarowana w zakresie okna, a nie w funkcji / zamknięciu.
xoxox,
2

Krótkie sposoby, które znalazłem do tej pory, aby uzyskać nazwę zmiennej jako ciąg:

const name = obj => Object.keys(obj)[0];

const whatsMyName = "Snoop Doggy Dogg";

console.log( "Variable name is: " + name({ whatsMyName }) );
//result: Variable name is: whatsMyName

Sebastian Knopp
źródło
1

To zadziałało przy użyciu Internet Explorera (9, 10 i 11), Google Chrome 5:

   
var myFirstName = "Danilo";
var varName = Object.keys({myFirstName:0})[0];
console.log(varName);

Tabela zgodności przeglądarek:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

danilo
źródło
Google Chrome 5? naprawdę??
lawina 1
2
@ avalanche1, zgodnie z tabelą kompatybilności wersji MDN.
danilo,
0

Stworzyłem tę funkcję w oparciu o JSON, jak ktoś zasugerował, działa dobrze dla moich potrzeb debugowania

function debugVar(varNames){
let strX = "";
function replacer(key, value){
    if (value === undefined){return "undef"}
    return value
    }    
for (let arg of arguments){
let lastChar;
    if (typeof arg!== "string"){
        let _arg = JSON.stringify(arg, replacer);
        _arg = _arg.replace('{',"");
        _arg = _arg.replace('}',"");            
        _arg = _arg.replace(/:/g,"=");
        _arg = _arg.replace(/"/g,"");
        strX+=_arg;
    }else{
    strX+=arg;
    lastChar = arg[arg.length-1];
    }
    if (arg!==arguments[arguments.length-1]&&lastChar!==":"){strX+=" "};
}
console.log(strX)    
}
let a = 42, b = 3, c;
debugVar("Begin:",{a,b,c},"end")

Igor Fomenko
źródło
-3

Nie, nie ma.
Poza tym, jeśli potrafisz pisać variablesName(myFirstName), znasz już nazwę zmiennej („myFirstName”).

zamrozić
źródło
11
Niekoniecznie prawda, jeśli kod jest zminimalizowany;)
Secret
9
Celem używania np. nameof(myVariable)W C # (który zwraca ciąg „myVariable”) jest ochrona przed błędami podczas refaktoryzacji lub wprowadzania innych zmian w kodzie. Typowym przypadkiem użycia jest dodanie nazwy zmiennej do generowanego komunikatu o błędzie. większość części, które uważam za dosłowne napisy, pachną kodem i podejrzewam, że właśnie dlatego przynajmniej Visual Studio pokazuje je w kolorze czerwono-pomarańczowym. Wiem, wiem, to pytanie dotyczy JavaScript, ale właśnie wyjaśniłem, dlaczego tutaj skończyłem.
merrr
var test = 1235125142; console.log (Object.keys ({test}). pop ()) // "test"
bluejayke
1
@bluejayke Nazywaj mnie ignorantem, ale po 8 latach wciąż nie rozumiem, jak to jest lepsze niż console.log('test')lub kiedy naprawdę tego potrzebujesz.
deceze