JavaScript'te dinamik değişken adları kullanma


344

PHP'de böyle şaşırtıcı / korkunç şeyler yapabilirsiniz:

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

Javascript ile böyle bir şey yapmanın bir yolu var mı?

Örneğin, bir var name = 'the name of the variable';değişkenim varsa değişkenli bir başvuru alabilir miyim name?


2
Stackoverflow.com/questions/724857/… ve stackoverflow.com/questions/1664282/… olası olası dupe , ancak burada kabul edilen cevap daha iyi, IMO.
goodeye

Bu sorunuza cevap veriyor mu? Javascript "değişken" değişkenleri? . Kabul edilen cevap buradakinden daha iyidir, çünkü nasıl yapılacağını gösterir, ancak aynı zamanda yapmak istediğiniz her şeyi yapmak için neredeyse her zaman daha iyi bir yol olduğu konusunda uyarır . Meta'daki XY sorununa bakın .
ggorlen

Yanıtlar:


354

ECMA- / Javascript tamamen Objectsve Contexts(ki bunlar aynı zamanda Nesneye de benzer) olduğundan, her değişken Değişken- (veya bir İşlev, Aktivasyon Nesnesi durumunda ) olarak adlandırılır.

Yani böyle değişkenler oluşturursanız:

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

Gelen Küresel kapsam (= HAYIR işlevi bağlam) kullanarak, örtülü içine bu değişkenleri yazma Küresel nesnesi (= windowbir tarayıcıda).

Bunlara "nokta" veya "köşeli ayraç" gösterimini kullanarak erişebilirsiniz:

var name = window.a;

veya

var name = window['a'];

Bunun nedeni sadece bu özel durumda küresel nesne için çalışır Değişken Nesne ait Küresel Nesne olan windownesne kendisi. Bir fonksiyonun bağlamında, Aktivasyon Nesnesine doğrudan erişiminiz yoktur . Örneğin:

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

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

new foobar();

newkendinden tanımlı bir nesnenin (bağlam) yeni bir örneğini oluşturur. newFonksiyonun kapsamı olmadan da global(= pencere) olur. Bu örnek sırasıyla uyarır undefinedve 1. Şununla değiştirirsek this.a = 1; this.b = 2:

var a = 1,
    b = 2;

Her iki uyarı çıkışı da tanımsız olacaktır. Bu senaryoda, değişkenler ave erişilemediğimiz bEtkinleştirme Nesnesinde saklanır foobar(tabii ki bunlara doğrudan arayarak erişebiliriz ave b).


1
Başka bir harika şey, bu şekilde herhangi bir küresel düzey işlevi için geri arama (başlangıç ​​/ bitiş) ekleyebilirsiniz.
antitoksik

5
Peki ya dinamik değişkenim bir fonksiyonda yerel ise? örneğin: işlev boink () {var a = 1; // bu işe yaramaz var dynamic = this ['a']; // bu da çalışmayacak var dynamic = ['a']; }
Kokodoko

@ Kokodoko — bu "bağlam" veya bir işlevin yürütme bağlamına bir referans olmadığı için (bir yürütme bağlamına başvurmanın bir yolu yoktur, ECMA-262 tarafından yasaklanmıştır). bu , bir işlevin nasıl çağrıldığına (veya bağlandığına ) göre ayarlanır , yalnızca erişilebilir olduğu yürütme bağlamıyla ilgisi olmayan bir Nesnedir.
RobG

Yuvalanmış mülklere erişmeniz gerekiyorsa stackoverflow.com/questions/4244896/…
Mr Br

köşeli parantez notasyonu ile beni doğru yöne çekti. Sadece nokta gösterimi düşünerek sıkışmıştı.
Andrew

149

eval bir seçenektir.

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

document.write(eval(name)); // 1

19
Hayır, eval kötü olduğu için olmamalıdır. Asla eval kullanmayın!
EasyBB

52
@EasyBB - asla bir şey kullanmamasını söyleyeceksen, nedenini açıklamakta yardımcı olmuyorum. Eval () dışında ne yaptığımı başarmak için başka bir yol düşünemiyorum bir durum var
Rampant Creative Group

4
Eval son kullanıcılara yönelik bir saldırı riski taşır ve biz teknik olarak kötü değil, bir vaka kaybında yanlış anlaşılır ve yanlış kullanılır. Ben kelimenin tam anlamıyla var php yanıtları gördüm sonra çalıştırmak için eval kullanın. Bu daha iyi yöntemler olduğu için bu durumda kullanılmamalıdır. Eldeki bu soru, genel olarak daha iyi yöntemler olduğu için hiç kullanılmamalıdır ve eminim ki birçoğumuz bunu biliyor.
EasyBB

2
Via javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval --- "Let en sık eval kullanılmasına karşı yöneltilen argümanlar göz önünde bulundurun: Bu bir derleme gerektirir ve) bu nedenle yavaş 2'dir 1) Ne olursa kötü niyetli komut dosyası değerlendirme argümanı yolunu buldu? 3) Çirkin görünüyor 4) Yürütme bağlamını ve çağrıldığı kapsamın bu bağlayıcılığını devralır
mattLummus

1
Eval

80

Pencere nesnesini ona ulaşmak için kullanabilirsiniz.

window['myVar']

window kullandığınız tüm global değişkenlere ve global işlevlere bir referansı vardır.


28
Söylemeye gerek yok, bu eval () 'den daha güvenlidir.
Cray

45

Kötü bir cevabın ne kadar oy aldığını bilmiyorum. Bu oldukça kolay bir cevap ama karmaşık hale getiriyorsunuz.

// 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);

13
"kullandığımız bir fonksiyonda this" - Global bir değişkene bu şekilde erişmek istiyorsanız , açık ve windownesneyi kullanmak daha iyidir this. thisBelirsiz.
MrWhite

1
Ancak bir işlevin içinde, örneğinizden thisdeğişkene erişmek için başka bir şey kullanamazsınız veya typeismini başka bir değişkene sahipseniz: function test(vname) { var type = 'article'; this[vname] = 'something else'; alert(type); }; test('type')göstermez article, göstermez something else. Ve "karmaşık cevap" da bunu açıklıyor.
Orafu

28
a = 'varname';
str = a+' = '+'123';
eval(str)
alert(varname);

Bunu dene...


27

Bu bir örnektir :

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

Başka bir örnek :

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

alert(coco); // display : riko

Yani, myVariable'ın " coco " değeri değişken bir coco olur .

Çünkü global kapsamdaki tüm değişkenler Window nesnesinin özellikleridir.


14

Javascript'te tüm özelliklerin anahtar değer çiftleri olduğu gerçeğini kullanabilirsiniz. jAndy bundan daha önce bahsetti ama cevabının nasıl sömürülebileceğini gösterdiğini sanmıyorum.

Genellikle bir değişken adını tutmak için bir değişken oluşturmaya çalışmıyorsunuz, ancak değişken adları oluşturmaya ve sonra kullanmaya çalışıyorsunuz. PHP $$vargösterimle bunu yapar, ancak özellik anahtarları dizi anahtarlarıyla değiştirilebilir olduğundan Javascript'in buna gerek yoktur.

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

Genellikle değişkeni inşa etmek istersiniz, bu yüzden dolaylı yol vardır, böylece bunu başka şekilde de yapabilirsiniz.

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

1
var someJsonObj = {}; bir döngüde .... for (var i = 0; i <= 3; i ++) {someJsonObj [i] = []; }, ama her şey olabilirim. böylece dinamik olarak oluşturulan değişkenler, hepsi kolay başvuru için someJsonObj içinde oturur.
rajeev

5

2019

TL; DR

  • eval operatör dize ifadesini çağrıldığı bağlamda çalıştırabilir ve bu bağlamdan değişkenler döndürebilir;
  • literal objectteorik olarak bunu yazma yoluyla yapabilir: {[varName]}ancak tanım gereği engellenmiştir.

Bu soruya rastlıyorum ve buradaki herkes gerçek bir çözüm getirmeden oynar. ama @Axel Heider iyi bir yaklaşıma sahip.

Çözüm eval. neredeyse en unutulan operatör. (çoğu kişinin olduğunu düşünüyorum with())

evalişleci ifadeyi çağrıldığı bağlamda dinamik olarak çalıştırabilir. ve bu ifadenin sonucunu döndürür. bunu fonksiyonun bağlamında bir değişkenin değerini dinamik olarak döndürmek için kullanabiliriz.

misal:

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

Her zaman açıkça ifade evalçalışacağını unutmayın. Kodda gereksiz sürprizlerden kaçınmak için. evalçok güçlü ama eminim ki zaten biliyorsun

BTW, yasal olsaydı literal object, değişken adını ve değerini yakalamak için kullanabilirdik , ancak hesaplanan özellik adlarını ve özellik değerini kısaca birleştiremiyoruz, ne yazık ki geçersiz

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

    var capture = {[varName]}

}

example('var1') //trow 'Uncaught SyntaxError: Unexpected token }`

Hızlı bir çözüm, ancak kötü bir uygulama çünkü JS motoru bu yöntemi optimize edemediğinden güvenli değil ve performansı düşürüyor.
Diego Ortiz

Müthiş çözüm
Rohit Parte

4

Pencere veya global (düğüm) gibi genel bir nesne kullanmak istemiyorsanız, şöyle bir şey deneyebilirsiniz:

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

console.log(obj['whatever']);

4

Sinek ve nesne şekilde iyi çalıştı birden çok FormData çizmek gerekiyordu

var forms = {}

Sonra benim döngülerde nerede kullandığım bir form veri oluşturmak için gerekli

forms["formdata"+counter]=new FormData();
forms["formdata"+counter].append(var_name, var_value);

Teşekkürler ... Tamamen kurtardı beni! $ refs ['listView' + dizin] .nativeView.animate ({..}) İhtiyacım var refs içinde böyle değişiyor. $ refs.listView1 listView2 vb ...
Meiki Neumann

2

Bu, dinamik olarak adlandırılmış bir değişkeni dışa aktarması gerekenler için bir alternatiftir

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

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

Başka bir alternatif, anahtarları dinamik olarak adlandırılan bir nesne oluşturmaktır

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

// consume it like this
vars[someVariable];

1

ne demek istedikleri hayır, yapamazsın. bunu yapmanın bir yolu yok. bu yüzden böyle bir şey yapabildin

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();

}

ECMAScript 5'te uygulanan gibi bir oluşturma işlevine sahip olmak.


4
Dikkat: const ES6
Tejas Manohar

4
... ve bundan önce geleceğe ayrılmış bir kelime vardı .
TJ Crowder

orada evaloperatör
Pery mimon

1

eval () testlerimde çalışmadı. Ancak DOM ağacına yeni JavaScript kodu eklemek mümkündür. İşte yeni bir değişken ekleyen bir fonksiyon:

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)

2
küçük bir gelişme, kimse var node_head = document.getElementsByTagName("head")[0]yerine bir kimlik id="head"vermek <head>:-) yerine kullanmak daha iyidir
ddlab

Yapıyorum :) Ama teşekkürler, şimdi nihayet bu `id =" kafa "şeyi kaldırabilirim
Axel Heider

1
Bu, küresel bir değişken yaratmanın aşırı karmaşık bir yolu gibi görünüyor mu ?! (... ve bu soruya nasıl cevap
veriyor

dahi :) eval çözümdür. Kodunuz çalışmıyor olsa bile
pery mimon

1

Bunun kabul edilmiş bir cevabı olmasına rağmen bir gözlem eklemek istiyorum:

ES6'da kullanma let işe yaramıyor :

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

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

Ancak eserleri kullanmavar

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

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

Umarım bu bazıları için faydalı olabilir.


1
aynı durum için geçerlidirconst

1
Doğru. Ama değişkenlere sahip bir nesne oluşturmak ve oradan değişkeni seçebilirsiniz: const vars = { t, m, b }; console.log(vars['b']). Aksi takdirde de evalçalışır.
Fabian von Ellerts

0

Nesne kullanmak da harika.

var a=123
var b=234
var temp = {"a":a,"b":b}
console.log(temp["a"],temp["b"]);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.