Verwenden Sie dynamische Variablennamen in JavaScript

344

In PHP können Sie erstaunliche / schreckliche Dinge wie diese tun:

$a = 1;
$b = 2;
$c = 3;
$name = 'a';
echo $$name;
// prints 1

Gibt es eine Möglichkeit, so etwas mit Javascript zu machen?

var name = 'the name of the variable';Kann ich beispielsweise einen Verweis auf die Variable mit dem Namen erhalten, wenn ich eine habe name?

Finbarr
quelle
2
Möglicher Betrug von stackoverflow.com/questions/724857/… und stackoverflow.com/questions/1664282/… , aber die akzeptierte Antwort hier besser, IMO.
Goodeye
Beantwortet das deine Frage? "Variable" Variablen in Javascript? . Die dort akzeptierte Antwort ist besser als die hier, weil sie zeigt, wie es geht, warnt aber auch richtig, dass es fast immer einen besseren Weg gibt, um das zu tun, was Sie wollen . Siehe XY-Problem auf Meta.
Ggorlen

Antworten:

353

Da es bei ECMA- / Javascript um Objectsund Contexts(die auch eine Art von Objekt sind) geht, wird jede Variable in einer so genannten Variablen- (oder im Fall einer Funktion, Aktivierungsobjekt ) gespeichert .

Wenn Sie also Variablen wie diese erstellen:

var a = 1,
    b = 2,
    c = 3;

Im globalen Bereich (= NO-Funktionskontext) schreiben Sie diese Variablen implizit in das globale Objekt (= windowin einem Browser).

Auf diese kann mit der Notation "Punkt" oder "Klammer" zugegriffen werden:

var name = window.a;

oder

var name = window['a'];

Dies funktioniert nur für das globale Objekt in dieser bestimmten Instanz, da das variable Objekt des globalen Objekts das windowObjekt selbst ist. Im Kontext einer Funktion haben Sie keinen direkten Zugriff auf das Aktivierungsobjekt . Zum Beispiel:

function foobar() {
   this.a = 1;
   this.b = 2;

   var name = window['a']; // === undefined
   alert(name);
   name = this['a']; // === 1
   alert(name);
}

new foobar();

newErstellt eine neue Instanz eines selbst definierten Objekts (Kontext). Ohne newden Umfang der Funktion wäre auch global(= Fenster). Dieses Beispiel würde alarmieren undefinedund 1jeweils. Wenn wir ersetzen würden durch this.a = 1; this.b = 2:

var a = 1,
    b = 2;

Beide Alarmausgaben wären undefiniert. In diesem Szenario werden die Variablen aund bim Aktivierungsobjekt gespeichert foobar, von dem aus wir nicht darauf zugreifen können (natürlich können wir direkt auf diese zugreifen, indem wir aund aufrufen b).

jAndy
quelle
1
Eine weitere coole Sache ist, dass Sie auf diese Weise einen Rückruf (Start / Ende) für jede Funktion auf globaler Ebene hinzufügen können.
Antitoxikum
5
Was aber, wenn meine dynamische Variable in einer Funktion lokal ist? zum Beispiel: function boink () {var a = 1; // das wird nicht funktionieren var dynamic = this ['a']; // das wird auch nicht funktionieren var dynamic = ['a']; }
Kokodoko
@ Kokodoko - da dies kein "Kontext" oder ein Verweis auf den Ausführungskontext einer Funktion ist (es gibt keine Möglichkeit, auf einen Ausführungskontext zu verweisen, dies ist vom ECMA-262 verboten). Dies wird dadurch festgelegt, wie eine Funktion aufgerufen wird (oder durch Binden ). Es handelt sich lediglich um ein Objekt, das nichts mit dem Ausführungskontext zu tun hat, auf den zugegriffen werden kann.
RobG
Wenn Sie auf verschachtelte Eigenschaften zugreifen müssen, besuchen
Mr Br
zeigte mir mit der Klammernotation in die richtige Richtung. Ich dachte nur an die Punktnotation.
Andrew
149

eval ist eine Option.

var a = 1;
var name = 'a';

document.write(eval(name)); // 1
erickb
quelle
19
Nein, es sollte nicht so sein, denn Eval ist böse. Verwenden Sie niemals eval!
EasyBB
52
@EasyBB - Wenn Sie sagen wollen, dass Sie niemals etwas verwenden sollen, ist es nicht hilfreich zu erklären, warum. Ich habe eine Situation, in der ich mir keinen anderen Weg vorstellen kann, um das zu erreichen, was ich tue, als eval ()
Rampant Creative Group
4
Eval birgt ein Risiko für Angriffe auf Endbenutzer, und wir werden feststellen, dass es technisch gesehen nicht böse ist, sondern in einem verlorenen Fall missverstanden und missbraucht wird. Ich habe PHP-Antworten gesehen, die wörtliche Variablen enthalten und dann eval verwenden, um es auszuführen. Dies sollte in diesem Fall jedoch nicht verwendet werden, da es bessere Methoden gibt. Diese Frage sollte überhaupt nicht verwendet werden, da es insgesamt bessere Methoden gibt, und ich bin sicher, dass viele von uns dies wissen.
EasyBB
2
Über javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval --- "Betrachten wir die Argumente, die am häufigsten gegen die Verwendung von eval gerichtet sind: 1) Es erfordert eine Kompilierung und ist daher langsam. 2) Was ist, wenn a böswilliges Skript hat seinen Weg in das eval-Argument gefunden? 3) Es sieht hässlich aus 4) Es erbt den Ausführungskontext und diese Bindung des Bereichs, in dem es aufgerufen wird "
mattLummus
1
Hier ist, wie man dynamische Variablen mit eval erstellt: stackoverflow.com/a/13291766/5528600
am2124429
80

Sie können das Fensterobjekt verwenden, um darauf zuzugreifen.

window['myVar']

window hat einen Verweis auf alle globalen Variablen und globalen Funktionen, die Sie verwenden.

JohnP
quelle
28
Und natürlich ist dieser sicherer als eval ().
Cray
45

Weiß nur nicht, was für eine schlechte Antwort so viele Stimmen bekommt. Es ist eine recht einfache Antwort, aber Sie machen es komplex.

// If you want to get article_count
// var article_count = 1000;
var type = 'article';
this[type+'_count'] = 1000;  // in a function we use "this";
alert(article_count);
Terry Lin
quelle
13
"in einer Funktion, die wir verwenden this" - Wenn Sie auf diese Weise auf eine globale Variable zugreifen möchten , ist es besser, explizit zu sein und das windowObjekt nicht zu verwenden this. thisist nicht eindeutig.
MrWhite
1
Aber innerhalb einer Funktion können Sie nicht thisoder nichts anderes verwenden, um typevon Ihrem Beispiel aus auf die Variable zuzugreifen , wenn Sie ihren Namen in einer anderen Variablen haben: function test(vname) { var type = 'article'; this[vname] = 'something else'; alert(type); }; test('type')wird angezeigt article, nicht something else. Und das erklärt die "komplexe Antwort".
Orafu
28
a = 'varname';
str = a+' = '+'123';
eval(str)
alert(varname);

Versuche dies...

amitchd
quelle
27

Dies ist ein Beispiel :

for(var i=0; i<=3; i++) {
    window['p'+i] = "hello " + i;
}

alert(p0); // hello 0
alert(p1); // hello 1
alert(p2); // hello 2
alert(p3); // hello 3

Ein anderes Beispiel :

var myVariable = 'coco';
window[myVariable] = 'riko';

alert(coco); // display : riko

Der Wert " coco " von myVariable wird also zu einem variablen coco .

Weil alle Variablen im globalen Bereich Eigenschaften des Window-Objekts sind.

Azodium
quelle
14

In Javascript können Sie die Tatsache verwenden, dass alle Eigenschaften Schlüsselwertpaare sind. jAndy hat dies bereits erwähnt, aber ich glaube nicht, dass seine Antwort zeigt, wie es ausgenutzt werden kann.

Normalerweise versuchen Sie nicht, eine Variable zu erstellen, die einen Variablennamen enthält, sondern versuchen, Variablennamen zu generieren und diese dann zu verwenden. PHP macht es mit $$varNotation, aber Javascript muss nicht, weil Eigenschaftsschlüssel mit Array-Schlüsseln austauschbar sind.

var id = "abc";
var mine = {};
mine[id] = 123;
console.log(mine.abc);

ergibt 123. Normalerweise möchten Sie die Variable konstruieren, weshalb es die Indirektion gibt, damit Sie es auch umgekehrt machen können.

var mine = {};
mine.abc = 123;
console.log(mine["a"+"bc"]);
David Newcomb
quelle
1
var someJsonObj = {}; in einer Schleife .... für (var i = 0; i <= 3; i ++) {someJsonObj [i] = []; }, aber ich kann alles sein. Bei dynamisch generierten Variablen befinden sich alle in someJsonObj, um eine einfache Referenz zu ermöglichen.
Rajeev
5

2019

TL; DR

  • eval Der Operator kann den Zeichenfolgenausdruck in dem aufgerufenen Kontext ausführen und Variablen aus diesem Kontext zurückgeben.
  • literal objecttheoretisch kann man das durch schreiben machen: {[varName]}aber es ist per definitionem blockiert.

Ich stoße also auf diese Frage und alle hier spielen einfach herum, ohne eine echte Lösung zu finden. aber @Axel Heider hat eine gute Annäherung.

Die Lösung ist eval. fast am meisten vergessener Betreiber. (denke, das meiste ist with())

evalDer Operator kann den Ausdruck in dem von ihm aufgerufenen Kontext dynamisch ausführen. und geben Sie das Ergebnis dieses Ausdrucks zurück. Damit können wir den Wert einer Variablen im Funktionskontext dynamisch zurückgeben.

Beispiel:

function exmaple1(){
   var a = 1, b = 2, default = 3;
   var name = 'a';
   return eval(name)
}

example1() // return 1


function example2(option){
  var a = 1, b = 2, defaultValue = 3;

  switch(option){
    case 'a': name = 'a'; break;
    case 'b': name = 'b'; break;
    default: name = 'defaultValue';
  }
  return eval (name);
}

example2('a') // return 1
example2('b') // return 2
example2() // return 3

Beachten Sie, dass ich immer explizit schreibe, dass der Ausdruck ausgeführt evalwird. Um unnötige Überraschungen im Code zu vermeiden. evalist sehr stark Aber ich bin sicher, dass Sie das schon wissen

Übrigens, wenn es legal wäre, könnten wir literal objectden Variablennamen und den Wert erfassen, aber wir können berechnete Eigenschaftsnamen und Eigenschaftswerte nicht kombinieren. Die Kurzschrift ist leider ungültig

functopn example( varName ){
    var var1 = 'foo', var2 ='bar'

    var capture = {[varName]}

}

example('var1') //trow 'Uncaught SyntaxError: Unexpected token }`
pery mimon
quelle
Es ist eine schnelle Lösung, aber es ist eine schlechte Praxis, da es nicht sicher ist und die Leistung verringert, da die JS-Engine diese Methode nicht optimieren kann.
Diego Ortiz
Tolle Lösung
Rohit Parte
4

Wenn Sie kein globales Objekt wie window oder global (node) verwenden möchten, können Sie Folgendes versuchen:

var obj = {};
obj['whatever'] = 'There\'s no need to store even more stuff in a global object.';

console.log(obj['whatever']);
Brent Barbata
quelle
4

Ich musste mehrere FormData im laufenden Betrieb zeichnen und die Objektweise funktionierten gut

var forms = {}

Dann in meinen Schleifen, wo immer ich Formulardaten erstellen musste, die ich verwendet habe

forms["formdata"+counter]=new FormData();
forms["formdata"+counter].append(var_name, var_value);
Talha
quelle
Danke ... Es hat mich total gerettet! this. $ refs ['listView' + index] .nativeView.animate ({..}) Ich brauchte Variablen in solchen Refs. $ refs.listView1 listView2 und so weiter ...
Meiki Neumann
2

Dies ist eine Alternative für diejenigen, die eine dynamisch benannte Variable exportieren müssen

export {
  [someVariable]: 'some value',
  [anotherVariable]: 'another value',
}

// then.... import from another file like this:
import * as vars from './some-file'

Eine andere Alternative besteht darin, einfach ein Objekt zu erstellen, dessen Schlüssel dynamisch benannt werden

const vars = { [someVariable]: 1, [otherVariable]: 2 };

// consume it like this
vars[someVariable];
JeanAlesi
quelle
1

was sie bedeuten ist nein, du kannst nicht. Es gibt keine Möglichkeit, dies zu erreichen. so war es möglich, dass Sie so etwas tun konnten

function create(obj, const){
// where obj is an object and const is a variable name
function const () {}

const.prototype.myProperty = property_value;
// .. more prototype

return new const();

}

eine Erstellungsfunktion haben, wie sie in ECMAScript 5 implementiert ist.

Alfgaar
quelle
4
Achtung: const ist ein Schlüsselwort in ES6
Tejas Manohar
4
... und davor war ein zukünftig reserviertes Wort .
TJ Crowder
Es gibt evalOperator
Pery Mimon
1

eval () hat in meinen Tests nicht funktioniert. Das Hinzufügen von neuem JavaScript-Code zum DOM-Baum ist jedoch möglich. Hier ist also eine Funktion, die eine neue Variable hinzufügt:

function createVariable(varName,varContent)
{
  var scriptStr = "var "+varName+"= \""+varContent+"\""

  var node_scriptCode = document.createTextNode( scriptStr )
  var node_script = document.createElement("script");
  node_script.type = "text/javascript"
  node_script.appendChild(node_scriptCode);

  var node_head = document.getElementsByTagName("head")[0]
  node_head.appendChild(node_script);
}

createVariable("dynamicVar", "some content")
console.log(dynamicVar)
Axel Heider
quelle
2
kleine Verbesserung, es ist besser, var node_head = document.getElementsByTagName("head")[0]anstelle von ID zu verwenden, da niemand ein gibt id="head"zu <head>:-)
ddlab
Das tue ich :) Aber danke, jetzt kann ich endlich dieses `id =" head "Ding entfernen
Axel Heider
1
Dies scheint nur eine zu komplexe Methode zum Erstellen einer globalen Variablen zu sein?! (... und wie beantwortet dies die Frage?)
MrWhite
Genie :) Eval ist die Lösung. Auch wenn Ihr Code nicht funktioniert
pery mimon
1

Obwohl dies eine akzeptierte Antwort hat, möchte ich eine Bemerkung hinzufügen:

In ES6 let funktioniert die Verwendung nicht :

/*this is NOT working*/
let t = "skyBlue",
    m = "gold",
    b = "tomato";

let color = window["b"];
console.log(color);

Jedoch mit var Arbeiten

/*this IS working*/
var t = "skyBlue",
    m = "gold",
    b = "tomato";

let color = window["b"];
console.log(color);

Ich hoffe, dass dies für einige nützlich sein kann.

Enxaneta
quelle
1
Gleiches gilt fürconst
1
Wahr. Sie können jedoch ein Objekt mit den Variablen erstellen und die Variable von dort auswählen : const vars = { t, m, b }; console.log(vars['b']). Ansonsten evalfunktioniert es auch.
Fabian von Ellerts
0

use Object ist auch großartig.

var a=123
var b=234
var temp = {"a":a,"b":b}
console.log(temp["a"],temp["b"]);
Steve Jiang
quelle