Gunakan nama variabel dinamis dalam JavaScript

344

Di PHP Anda dapat melakukan hal-hal luar biasa / mengerikan seperti ini:

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

Apakah ada cara melakukan hal seperti ini dengan Javascript?

Misal jika saya punya, var name = 'the name of the variable';bisakah saya mendapatkan referensi ke variabel dengan nama name?

Finbarr
sumber
2
Kemungkinan penipuan stackoverflow.com/questions/724857/… , dan stackoverflow.com/questions/1664282/… , tetapi jawaban yang diterima di sini lebih baik, IMO.
selamat tinggal
Apakah ini menjawab pertanyaan Anda? Variabel "Variabel" di Javascript? . Jawaban yang diterima di sana lebih baik daripada yang ada di sini karena itu menunjukkan bagaimana melakukannya, tetapi juga dengan benar memperingatkan bahwa hampir selalu ada cara yang lebih baik untuk melakukan apa pun yang ingin Anda lakukan . Lihat masalah XY pada meta.
ggorlen

Jawaban:

353

Karena ECMA- / Javascript adalah semua tentang Objectsdan Contexts(yang, juga merupakan objek dari Object), setiap variabel disimpan dalam variabel yang disebut Variable- (atau dalam hal Function, Activation Object ).

Jadi jika Anda membuat variabel seperti ini:

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

Dalam lingkup Global (= NO konteks fungsi), Anda secara implisit menulis variabel-variabel tersebut ke objek Global (= windowdalam browser).

Itu dapat diakses dengan menggunakan notasi "dot" atau "bracket":

var name = window.a;

atau

var name = window['a'];

Ini hanya bekerja untuk obyek global dalam contoh khusus ini, karena Obyek Variabel dari Object global adalah windowobjek itu sendiri. Dalam Konteks fungsi, Anda tidak memiliki akses langsung ke Objek Aktivasi . Contohnya:

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

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

new foobar();

newmenciptakan instance baru dari objek yang didefinisikan sendiri (konteks). Tanpa newruang lingkup fungsi akan juga global(= window). Contoh ini akan mengingatkanundefined dan 1masing - masing. Jika kami akan mengganti this.a = 1; this.b = 2dengan:

var a = 1,
    b = 2;

Kedua keluaran peringatan akan tidak ditentukan. Dalam skenario itu, variabel adan bakan disimpan di Objek Aktivasi dari foobar, yang tidak dapat kita akses (tentu saja kita dapat mengaksesnya secara langsung dengan menelepon adan b).

jandy
sumber
1
Hal keren lainnya adalah dengan cara ini Anda dapat menambahkan panggilan balik (mulai / selesai) untuk fungsi tingkat global apa pun.
antitoksik
5
Tetapi bagaimana jika variabel dinamis saya adalah fungsi lokal? misalnya: function boink () {var a = 1; // ini tidak akan berfungsi var dynamic = this ['a']; // ini juga tidak akan bekerja var dynamic = ['a']; }
Kokodoko
@ Kokodoko — karena ini bukan "konteks" atau referensi ke konteks eksekusi fungsi (tidak ada cara untuk referensi konteks eksekusi, itu dilarang oleh ECMA-262). ini diatur oleh bagaimana suatu fungsi dipanggil (atau oleh bind ), itu hanya sebuah Objek yang tidak ada hubungannya dengan konteks eksekusi di mana ia dapat diakses.
RobG
Jika Anda perlu mengakses properti bersarang, periksa stackoverflow.com/questions/4244896/…
Mr Br
menunjuk saya ke arah yang benar dengan notasi braket. Terjebak hanya memikirkan titik notasi.
Andrew
149

eval adalah salah satu pilihan.

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

document.write(eval(name)); // 1
erickb
sumber
19
Tidak seharusnya tidak karena eval itu jahat. Jangan pernah gunakan eval!
EasyBB
52
@EasyBB - jika Anda akan mengatakan tidak pernah menggunakan sesuatu, saya tidak membantu menjelaskan alasannya. Saya memiliki situasi di mana saya tidak dapat memikirkan cara lain untuk menyelesaikan apa yang saya lakukan selain eval ()
Rampant Creative Group
4
Eval menimbulkan risiko serangan terhadap pengguna akhir dan kami tidak akan secara teknis jahat, melainkan disalahpahami dan disalahgunakan dalam kasus yang hilang. Saya telah melihat respons php yang menyimpan vars literal di dalamnya lalu gunakan eval untuk menjalankannya. Meskipun ini tidak boleh digunakan dalam kasus ini karena ada metode yang lebih baik. Pertanyaan ini sebaiknya tidak digunakan sama sekali karena ada metode yang lebih baik secara keseluruhan dan saya yakin banyak dari kita tahu ini.
EasyBB
2
Melalui javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval --- "Mari kita pertimbangkan argumen yang paling sering dilontarkan terhadap penggunaan eval: 1) Ini membutuhkan kompilasi dan karena itu lambat 2) Bagaimana jika suatu skrip berbahaya menemukan jalannya ke argumen eval? 3) Kelihatannya jelek 4) Itu mewarisi konteks eksekusi dan pengikatan lingkup tempat ini dipanggil "
mattLummus
1
Berikut adalah cara membuat variabel dinamis menggunakan eval: stackoverflow.com/a/13291766/5528600
am2124429
80

Anda dapat menggunakan objek jendela untuk mendapatkannya.

window['myVar']

window memiliki referensi ke semua variabel global dan fungsi global yang Anda gunakan.

JohnP
sumber
28
Dan tentu saja, ini lebih aman daripada eval ().
Cray
45

Hanya tidak tahu jawaban buruk apa yang mendapat begitu banyak suara. Ini jawaban yang cukup mudah tetapi Anda membuatnya rumit.

// 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
sumber
13
"dalam fungsi yang kami gunakan this" - Jika Anda ingin mengakses variabel global dengan cara ini, lebih baik untuk eksplisit dan menggunakan windowobjek, bukan this. thisambigu.
MrWhite
1
Tetapi di dalam suatu fungsi Anda tidak dapat menggunakan this, atau apa pun, untuk mengakses variabel typedari contoh Anda, jika Anda memiliki namanya di variabel lain: function test(vname) { var type = 'article'; this[vname] = 'something else'; alert(type); }; test('type')akan ditampilkan article, tidak something else. Dan itulah yang dijelaskan "jawaban kompleks".
Orafu
28
a = 'varname';
str = a+' = '+'123';
eval(str)
alert(varname);

Coba ini...

amitchd
sumber
27

Ini adalah sebuah contoh:

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

Contoh lain :

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

alert(coco); // display : riko

Jadi, nilai " coco " dari myVariable menjadi variabel coco .

Karena semua variabel dalam lingkup global adalah properti dari objek Window.

Azodium
sumber
14

Dalam Javascript Anda dapat menggunakan fakta bahwa semua properti adalah pasangan nilai kunci. jAndy sudah menyebutkan ini, tapi saya pikir jawabannya tidak menunjukkan bagaimana itu bisa dieksploitasi.

Biasanya Anda tidak mencoba membuat variabel untuk menyimpan nama variabel tetapi mencoba untuk menghasilkan nama variabel dan kemudian menggunakannya. PHP melakukannya dengan $$varnotasi tetapi Javascript tidak perlu karena kunci properti dapat dipertukarkan dengan kunci array.

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

memberikan 123. Biasanya Anda ingin membangun variabel yang mengapa ada tipuan sehingga Anda juga bisa melakukannya sebaliknya.

var mine = {};
mine.abc = 123;
console.log(mine["a"+"bc"]);
David Newcomb
sumber
1
var someJsonObj = {}; dalam satu lingkaran .... untuk (var i = 0; i <= 3; i ++) {someJsonObj [i] = []; }, tetapi saya bisa menjadi apa saja. variabel yang dihasilkan secara dinamis, semua duduk di dalam someJsonObj untuk referensi mudah.
rajeev
5

2019

TL; DR

  • eval operator dapat menjalankan ekspresi string dalam konteks yang dipanggil dan mengembalikan variabel dari konteks itu;
  • literal objectsecara teoritis dapat melakukannya dengan menulis:, {[varName]}tetapi diblokir oleh definisi.

Jadi saya menemukan pertanyaan ini dan semua orang di sini hanya bermain-main tanpa membawa solusi nyata. tapi @Axel Heider memiliki pendekatan yang bagus.

Solusinya adalah eval. operator yang hampir terlupakan. (Berpikir kebanyakan adalahwith() )

evalOperator dapat secara dinamis menjalankan ekspresi dalam konteks yang disebutnya. dan kembalikan hasil dari ekspresi itu. kita dapat menggunakannya untuk mengembalikan nilai variabel secara dinamis dalam konteks fungsi.

contoh:

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

Perhatikan bahwa saya selalu menulis secara eksplisit ekspresi evalakan berjalan. Untuk menghindari kejutan yang tidak perlu dalam kode. evalsangat kuat Tapi saya yakin Anda sudah tahu itu

BTW, jika itu legal, kita dapat menggunakan literal objectuntuk menangkap nama variabel dan nilai, tetapi kita tidak dapat menggabungkan nama properti yang dihitung dan singkatan nilai properti, sayangnya, tidak valid

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

    var capture = {[varName]}

}

example('var1') //trow 'Uncaught SyntaxError: Unexpected token }`
pery mimon
sumber
Ini solusi cepat, tetapi ini adalah praktik yang buruk karena tidak aman dan menurunkan kinerja karena mesin JS tidak dapat mengoptimalkan metode itu.
Diego Ortiz
Solusi luar biasa
Rohit Parte
4

Jika Anda tidak ingin menggunakan objek global seperti jendela atau global (simpul), Anda dapat mencoba sesuatu seperti ini:

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

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

Saya perlu menggambar beberapa FormData dengan cepat dan cara objek bekerja dengan baik

var forms = {}

Kemudian di loop saya di mana pun saya perlu membuat data formulir yang saya gunakan

forms["formdata"+counter]=new FormData();
forms["formdata"+counter].append(var_name, var_value);
Talha
sumber
Terima kasih ... Ini benar-benar menyelamatkan saya! ini. $ refs ['listView' + index] .nativeView.animate ({..}) Saya membutuhkan vars di dalam ref seperti ini. $ refs.listView1 listView2 dan seterusnya ...
Meiki Neumann
2

Ini adalah alternatif bagi mereka yang perlu mengekspor variabel yang dinamai secara dinamis

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

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

Alternatif lain adalah dengan hanya membuat objek yang kuncinya dinamai secara dinamis

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

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

apa yang mereka maksudkan adalah tidak, Anda tidak bisa. tidak ada cara untuk menyelesaikannya. jadi mungkin saja kamu bisa melakukan hal seperti ini

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

}

memiliki fungsi create sama seperti yang diterapkan pada ECMAScript 5.

Alfgaar
sumber
4
Hati-hati: const adalah kata kunci dalam ES6
Tejas Manohar
4
... dan sebelum itu adalah kata masa depan yang dicadangkan .
TJ Crowder
ada evaloperator
pery mimon
1

eval () tidak berfungsi dalam pengujian saya. Tetapi menambahkan kode JavaScript baru ke pohon DOM adalah mungkin. Jadi di sini adalah fungsi yang menambahkan variabel baru:

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
sumber
2
perbaikan kecil, lebih baik untuk menggunakan var node_head = document.getElementsByTagName("head")[0]bukan ID, karena tidak ada yang memberikan id="head"untuk <head>:-)
ddlab
Saya lakukan :) Tapi terima kasih, sekarang saya akhirnya dapat menghapus hal `id =" head "ini
Axel Heider
1
Ini sepertinya merupakan cara yang terlalu rumit untuk menciptakan variabel global ?! (... dan bagaimana ini menjawab pertanyaan?)
MrWhite
genius :) eval adalah solusinya. Bahkan jika kode Anda tidak berfungsi
pery mimon
1

Meskipun ini memiliki jawaban yang diterima, saya ingin menambahkan pengamatan:

Dalam ES6 menggunakan let tidak berfungsi :

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

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

Namun menggunakan var karya

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

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

Saya harap ini bermanfaat bagi sebagian orang.

enxaneta
sumber
1
hal yang sama berlaku untukconst
1
Benar. Tapi Anda bisa membuat obyek dengan variabel dan pilih variabel dari sana: const vars = { t, m, b }; console.log(vars['b']). Jika tidak evalberfungsi juga.
Fabian von Ellerts
0

gunakan Object juga bagus.

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