Mengakses properti objek secara dinamis menggunakan variabel

Jawaban:

959

Ada dua cara untuk mengakses properti dari suatu objek:

  • Notasi dot: something.bar
  • Notasi braket: something['bar']

Nilai antara tanda kurung dapat berupa ekspresi apa pun. Oleh karena itu, jika nama properti disimpan dalam variabel, Anda harus menggunakan notasi braket:

var foo = 'bar';
something[foo];
// both x = something[foo] and something[foo] = x work as expected
Jan Hančič
sumber
34
hati-hati dengan ini: kompiler javascript akan kesalahan di sini karena mereka tidak mengganti nama string tetapi mereka mengganti nama properti objek
chacham15
6
Beberapa info lebih lanjut tentang mengapa ini mungkin: objek JS adalah array asosiatif, itu sebabnya. Bacaan Lebih Lanjut: quirksmode.org/js/associative.html stackoverflow.com/questions/14031368/…
Sudhanshu Mishra
@dotnetguy Tidak mereka tidak. Array adalah objek yang mewarisi dari prototipe objek JS biasa dan karena itu Anda dapat menambahkan properti go-go seperti objek biasa. Perilaku 'asosiatif' lebih seperti objek daripada seperti array. Anda tidak dapat mengulangi versi 'asosiatif' dengan indeks sederhana sehingga tidak menampilkan perilaku seperti array. Anda dapat mendefinisikan larik 'asosiatif' Anda sebagai {} atau [] dan memperlakukannya sama dalam kedua kasus sejauh menyangkut akses properti acak.
Vanquished Wombat
3
@ VanquishedWombat Tidak yakin dengan apa keberatan Anda? Saya tidak mengatakan bahwa Obyek JS adalah array?
Sudhanshu Mishra
1
Jawaban ini terlalu banyak dipilih, tidak mengklarifikasi apa pun ...
Aft3rL1f3
104

Ini solusi saya:

function resolve(path, obj) {
    return path.split('.').reduce(function(prev, curr) {
        return prev ? prev[curr] : null
    }, obj || self)
}

Contoh penggunaan:

resolve("document.body.style.width")
// or
resolve("style.width", document.body)
// or even use array indexes
// (someObject has been defined in the question)
resolve("part.0.size", someObject) 
// returns null when intermediate properties are not defined:
resolve('properties.that.do.not.exist', {hello:'world'})
abahet
sumber
Jawaban luar biasa, lihat juga: stackoverflow.com/questions/37510640/…
Julian Knight
2
Anda mengilhami saya untuk membuat versi yang disempurnakan yang memungkinkan notasi braket & nama properti dengan spasi serta memvalidasi input: it.knightnet.org.uk/kb/node-js/get-properties
Julian Knight
Saya suka solusi ini. Namun saya mencoba untuk memodifikasi nilai-nilai dalam objek asli, sepertinya fungsi Anda mengembalikan sub salinan objek. Apakah mungkin untuk mengubahnya sehingga memodifikasi objek yang dikembalikan memodifikasi yang asli?
Eagle1
40

Dalam javascript kita dapat mengakses dengan:

  • notasi titik - foo.bar
  • kurung kotak - foo[someVar]ataufoo["string"]

Tetapi hanya case kedua yang memungkinkan untuk mengakses properti secara dinamis:

var foo = { pName1 : 1, pName2 : [1, {foo : bar }, 3] , ...}

var name = "pName"
var num  = 1;

foo[name + num]; // 1

// -- 

var a = 2;
var b = 1;
var c = "foo";

foo[name + a][b][c]; // bar
Sonique
sumber
4
Saya menatap 2.000 baris pernyataan if karena dev sebelumnya tidak menggunakan tanda kurung siku, dan properti objek diakses secara statis dengan notasi titik. Ini untuk aplikasi proses persetujuan yang memiliki 7 penerima berbeda dan langkah-langkahnya sama. / rip
Chad
26

Berikut ini adalah contoh ES6 tentang bagaimana Anda dapat mengakses properti suatu objek menggunakan nama properti yang telah dihasilkan secara dinamis dengan menggabungkan dua string.

var suffix = " name";

var person = {
    ["first" + suffix]: "Nicholas",
    ["last" + suffix]: "Zakas"
};

console.log(person["first name"]);      // "Nicholas"
console.log(person["last name"]);       // "Zakas"

Ini disebut nama properti yang dihitung

zloctb
sumber
16

Anda dapat mencapai ini dalam beberapa cara yang berbeda.

let foo = {
    bar: 'Hello World'
};

foo.bar;
foo['bar'];

Notasi braket sangat kuat karena memungkinkan Anda mengakses properti berdasarkan variabel:

let foo = {
    bar: 'Hello World'
};

let prop = 'bar';

foo[prop];

Ini dapat diperluas untuk mengulang setiap properti dari suatu objek. Ini bisa tampak berlebihan karena konstruksi JavaScript yang lebih baru seperti untuk ... dari ..., tetapi membantu mengilustrasikan kasus penggunaan:

let foo = {
    bar: 'Hello World',
    baz: 'How are you doing?',
    last: 'Quite alright'
};

for (let prop in foo.getOwnPropertyNames()) {
    console.log(foo[prop]);
}

Notasi titik dan braket juga berfungsi seperti yang diharapkan untuk objek bersarang:

let foo = {
    bar: {
        baz: 'Hello World'
    }
};

foo.bar.baz;
foo['bar']['baz'];
foo.bar['baz'];
foo['bar'].baz;

Destrukturisasi objek

Kita juga dapat mempertimbangkan perusakan objek sebagai sarana untuk mengakses properti di suatu objek, tetapi sebagai berikut:

let foo = {
    bar: 'Hello World',
    baz: 'How are you doing?',
    last: 'Quite alright'
};

let prop = 'last';
let { bar, baz, [prop]: customName } = foo;

// bar = 'Hello World'
// baz = 'How are you doing?'
// customName = 'Quite alright'
Gorka Hernandez
sumber
11

Anda bisa melakukannya seperti ini menggunakan Lodash get

_.get(object, 'a[0].b.c');
shalonteoh
sumber
Ada banyak situasi, seperti pencarian objek bersarang dalam, di mana ini adalah satu-satunya pilihan.
Jonathan Kempf
8

DIPERBARUI

Saya telah mempertimbangkan komentar di bawah ini dan menyetujui. Eval harus dihindari.

Mengakses properti root pada objek mudah dicapai obj[variable], tetapi bersarang menjadi hal yang rumit. Jangan menulis kode yang sudah ditulis saya sarankan untuk digunakan lodash.get.

Contoh

// Accessing root property
var rootProp = 'rootPropert';
_.get(object, rootProp, defaultValue);

// Accessing nested property
var listOfNestedProperties = [var1, var2];
_.get(object, listOfNestedProperties);

Lodash get dapat digunakan dengan berbagai cara, berikut ini tautan ke dokumentasi lodash.get

Tuan Br
sumber
4
Sebaiknya hindari penggunaan evalbila memungkinkan. stackoverflow.com/questions/86513/…
Luke
8
Menggunakan evaluntuk sesuatu yang sepele seperti mengakses properti adalah pekerjaan biasa-biasa saja dan hampir tidak dianjurkan dalam keadaan apa pun. Apa itu "masalah"? obj['nested']['test']berfungsi dengan sangat baik dan tidak mengharuskan Anda untuk menanamkan kode dalam string.
Kyll
3
eval tiga kali lebih lambat atau lebih, saya tidak akan merekomendasikan ini kepada pemula karena mungkin mengajarkan mereka kebiasaan buruk. Saya menggunakan obj['nested']['value']- ingat anak-anak, eval itu jahat!
jaggedsoft
1
@ Lukas Dia sekarang satu-satunya yang ingin membawa Lodash _.getke meja. Saya pikir jawaban ini pantas sekarang naik bukan turun turun. Ini mungkin berlebihan, tetapi ada baiknya untuk mengetahui bahwa itu ada.
Emile Bergeron
1
Terima kasih telah memperkenalkan lodash untuk ini. Saya datang ke sini oleh google mencari metode untuk menetapkan nilai jauh di dalam suatu objek, dan menggunakan metode _.set mereka (yang identik dengan di atas tetapi dengan argumen tambahan untuk nilai yang ditetapkan).
TPHughes
5

Kapan pun Anda perlu mengakses properti secara dinamis, Anda harus menggunakan braket persegi untuk mengakses properti bukan "." Sintaks operator
: objek [layak}

const something = { bar: "Foobar!" };
const foo = 'bar';
// something.foo; -- not correct way at it is expecting foo as proprty in  something={ foo: "value"};
// correct way is  something[foo]
alert( something[foo])

Rupesh Agrawal
sumber
4

Saya menemukan sebuah kasus di mana saya pikir saya ingin meneruskan "alamat" properti objek sebagai data ke fungsi lain dan mengisi objek (dengan AJAX), melakukan pencarian dari array alamat, dan menampilkan dalam fungsi lainnya. Saya tidak bisa menggunakan notasi titik tanpa melakukan string akrobat, jadi saya pikir array mungkin lebih baik untuk dilewatkan. Saya akhirnya melakukan sesuatu yang berbeda, tetapi sepertinya terkait dengan posting ini.

Berikut ini contoh objek file bahasa seperti yang saya inginkan dari data:

const locs = {
  "audioPlayer": {
    "controls": {
      "start": "start",
      "stop": "stop"
    },
    "heading": "Use controls to start and stop audio."
  }
}

Saya ingin dapat melewatkan array seperti: ["audioPlayer", "kontrol", "stop"] untuk mengakses teks bahasa, "stop" dalam kasus ini.

Saya membuat fungsi kecil ini yang mencari parameter alamat "paling tidak spesifik" (pertama), dan menugaskan kembali objek yang dikembalikan ke dirinya sendiri. Kemudian siap untuk mencari parameter alamat berikutnya yang paling spesifik jika ada.

function getText(selectionArray, obj) {
  selectionArray.forEach(key => {
    obj = obj[key];
  });
  return obj;
}

pemakaian:

/* returns 'stop' */
console.log(getText(["audioPlayer", "controls", "stop"], locs)); 

/* returns 'use controls to start and stop audio.' */
console.log(getText(["audioPlayer", "heading"], locs)); 
Luke
sumber
2

Menjadi menarik ketika Anda harus memberikan parameter ke fungsi ini juga.

Kode jsfiddle

var obj = {method:function(p1,p2,p3){console.log("method:",arguments)}}

var str = "method('p1', 'p2', 'p3');"

var match = str.match(/^\s*(\S+)\((.*)\);\s*$/);

var func = match[1]
var parameters = match[2].split(',');
for(var i = 0; i < parameters.length; ++i) {
  // clean up param begninning
    parameters[i] = parameters[i].replace(/^\s*['"]?/,'');
  // clean up param end
  parameters[i] = parameters[i].replace(/['"]?\s*$/,'');
}

obj[func](parameters); // sends parameters as array
obj[func].apply(this, parameters); // sends parameters as individual values
Jacksonkr
sumber
1

ES5 // Periksa Variabel yang Sangat Bersarang

Sepotong kode sederhana ini dapat memeriksa keberadaan variabel / nilai yang sangat bersarang tanpa harus memeriksa setiap variabel di sepanjang jalan ...

var getValue = function( s, context ){
    return Function.call( context || null, 'return ' + s )();
}

Ex. - berbagai objek yang bersarang:

a = [ 
    {
      b : [
          {
             a : 1,
             b : [
                 {
                    c : 1,
                    d : 2   // we want to check for this
                 }
             ]
           }
      ]
    } 
]

Dari pada :

if(a && a[0] && a[0].b && a[0].b[0] && a[0].b[0].b && a[0].b[0].b[0] && a[0].b[0].b[0].d && a[0].b[0].b[0].d == 2 )  // true

Kita sekarang bisa:

if( getValue('a[0].b[0].b[0].d') == 2 ) // true

Bersulang!


sumber
1
Jika solusinya adalah menggunakan eval, Anda baru saja membuat sejuta masalah lainnya.
Rodrigo Leite
@RodrigoLeite ok, jadi tidak akan menjadi masalah untuk memberikan setidaknya satu ...
1
@RodrigoLeite Saya telah membacanya, dan memperbarui solusi untuk digunakan Functionsebagai gantinya
0

Saya mengajukan pertanyaan yang agak digandakan pada topik ini beberapa waktu lalu, dan setelah penelitian yang berlebihan, dan melihat banyak informasi yang hilang yang seharusnya ada di sini, saya merasa ada sesuatu yang berharga untuk ditambahkan ke pos lama ini.

  • Pertama saya ingin membahas bahwa ada beberapa cara untuk mendapatkan nilai properti dan menyimpannya dalam Variabel dinamis. Cara IMHO paling populer pertama dan termudah adalah:
let properyValue = element.style['enter-a-property'];

namun saya jarang menggunakan rute ini karena tidak bekerja pada nilai properti yang ditetapkan melalui style-sheet. Untuk memberi Anda contoh, saya akan menunjukkan dengan sedikit kode semu.

 let elem = document.getElementById('someDiv');
 let cssProp = elem.style['width'];

Menggunakan contoh kode di atas; jika properti lebar elemen div yang disimpan dalam variabel 'elem' ditata dalam lembar gaya CSS, dan tidak ditata di dalam tag HTML-nya, Anda tanpa ragu akan mendapatkan nilai pengembalian dari undefined yang disimpan di dalam dari variabel cssProp. Nilai yang tidak ditentukan terjadi karena untuk mendapatkan nilai yang benar, kode yang ditulis dalam CSS Style-Sheet perlu dihitung untuk mendapatkan nilai, oleh karena itu; Anda harus menggunakan metode yang akan menghitung nilai properti yang nilainya terletak di dalam style-sheet.

  • Selanjutnya metode getComputedStyle ()!
function getCssProp(){
  let ele = document.getElementById("test");
  let cssProp = window.getComputedStyle(ele,null).getPropertyValue("width");
}

W3Schools getComputedValue Doc Ini memberikan contoh yang baik, dan memungkinkan Anda bermain dengannya, namun, tautan ini Mozilla CSS getComputedValue doc berbicara tentang fungsi getComputedValue secara terperinci, dan harus dibaca oleh setiap calon pengembang yang tidak sepenuhnya mengerti tentang subjek ini.

  • Sebagai catatan, metode getComputedValue hanya didapat, tidak disetel. Ini, jelas merupakan kelemahan utama, namun ada metode yang didapat dari style sheet CSS, serta nilai set, meskipun itu bukan Javascript standar. Metode JQuery ...
$(selector).css(property,value)

... Apakah mendapatkan, dan tidak diatur. Ini yang saya gunakan, satu-satunya downside adalah Anda harus tahu JQuery, tapi ini jujur ​​salah satu dari banyak alasan bagus bahwa setiap Pengembang Javascript harus belajar JQuery, itu hanya membuat hidup lebih mudah, dan menawarkan metode, seperti ini, yang tidak tersedia dengan Javascript standar. Semoga ini bisa membantu seseorang !!!

Aft3rL1f3
sumber
0

Bagi siapa pun yang ingin mengatur nilai variabel bersarang, berikut adalah cara melakukannya:

const _ = require('lodash'); //import lodash module

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4

Dokumentasi: https://lodash.com/docs/4.17.15#set

Juga, dokumentasi jika Anda ingin mendapatkan nilai: https://lodash.com/docs/4.17.15# get

GavinBelson
sumber
-3

Anda harus menggunakan JSON.parse, lihat di https://www.w3schools.com/js/js_json_parse.asp

const obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}')
console.log(obj.name)
console.log(obj.age)
onmyway133
sumber
-4
const something = { bar: "Foobar!" };
const foo = 'bar';

something[\`${foo}\`];
Sergey
sumber
7
Mengapa kamu mau melakukan itu? Anda foosudah menjadi string, jadi `${foo}`persis sama dengan foo. (Juga, kode Anda tampaknya memiliki beberapa garis miring terbalik tambahan yang tidak seharusnya ada di sana. Tapi itu tetap tidak ada gunanya bahkan jika Anda memperbaiki kesalahan sintaksis itu.)
Ilmari Karonen