Değişken kullanarak nesne özelliğine dinamik olarak erişin


Yanıtlar:


964

Bir nesnenin özelliklerine erişmenin iki yolu vardır :

  • Nokta gösterimi: something.bar
  • Braket gösterimi: something['bar']

Köşeli ayraçlar arasındaki değer herhangi bir ifade olabilir. Bu nedenle, özellik adı bir değişkende depolanırsa, parantez notasyonu kullanmanız gerekir:

var foo = 'bar';
something[foo];
// both x = something[foo] and something[foo] = x work as expected

34
dikkatli olun: javascript derleyicileri burada dizeleri yeniden adlandırmazlar ama nesne özelliklerini yeniden adlandırırlar çünkü hata verecektir
chacham15

6
Bunun neden mümkün olduğu hakkında daha fazla bilgi: JS nesneleri ilişkilendirilebilir dizilerdir, bu yüzden. Daha fazla okuma: quirksmode.org/js/associative.html stackoverflow.com/questions/14031368/…
Mishra

@dotnetguy Hayır değiller. Diziler, düz JS nesne prototipinden devralınan nesnelerdir ve bu nedenle herhangi bir düz nesne gibi bir go-go özellikleri ekleyebilirsiniz. 'İlişkilendirici' davranış, dizi gibi olmaktan çok nesneye benzer. 'İlişkisel' sürümü basit bir dizine göre yineleyemezsiniz, bu nedenle dizi benzeri davranışlar göstermez. 'İlişkilendirici' dizinizi {} veya [] olarak tanımlayabilir ve her iki durumda da rastgele özellik erişimi söz konusu olduğunda aynı davranabilirsiniz.
Vanomished Wombat

3
@VanquishedWombat İtirazınızın ne ile ilgili olduğundan emin değil misiniz? Ben JS Nesneleri diziler olduğunu söylemedim?
Sudhanshu Mishra

1
Bu cevap çok fazla oy aldı, hiçbir şeyi netleştirmiyor ...
Aft3rL1f3

104

Bu benim çözümüm:

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

Kullanım örnekleri:

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'})

Mükemmel cevap, ayrıca bakınız: stackoverflow.com/questions/37510640/…
Julian Knight

2
Girişleri doğrulamanın yanı sıra boşluklarla parantez notasyonu ve özellik adlarına izin veren gelişmiş bir sürüm oluşturmam için bana ilham verdiniz: it.knightnet.org.uk/kb/node-js/get-properties
Julian Knight

Bu çözümü seviyorum. Ancak orijinal nesnenin değerlerini değiştirmeye çalışıyorum, işlevinizin nesnenin bir alt kopyasını döndürür gibi görünüyor. Döndürülen nesneyi değiştirmek orijinali değiştirecek şekilde değiştirmek mümkün müdür?
Eagle1

40

Javascript ile şunlara erişebiliriz:

  • nokta gösterimi - foo.bar
  • köşeli ayraçlar - foo[someVar]veyafoo["string"]

Ancak yalnızca ikinci durum, özelliklere dinamik olarak erişmeyi sağlar:

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

5
Önceki dev köşeli parantez kullanmadıysanız ve nokta gösterimiyle statik olarak erişilen nesne özelliklerinden dolayı if ifadelerinin 2.000 satırına bakıyorum. 7 farklı onaylayıcıya sahip bir onay süreci uygulaması içindir ve adımların hepsi aynıdır. / Rip
Chad

27

Aşağıda, iki dizeyi birleştirerek dinamik olarak oluşturulmuş bir özellik adını kullanarak bir nesnenin özelliğine nasıl erişebileceğinize ilişkin bir ES6 örneği verilmiştir.

var suffix = " name";

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

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

Buna hesaplanmış özellik adları denir


16

Bunu birkaç farklı yolla başarabilirsiniz.

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

foo.bar;
foo['bar'];

Köşeli ayraç notasyonu, bir değişkene dayalı bir özelliğe erişmenize izin verdiği için özellikle güçlüdür:

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

let prop = 'bar';

foo[prop];

Bu, bir nesnenin her özelliği üzerinde döngü oluşturacak şekilde genişletilebilir. Bu, ... gibi ... gibi daha yeni JavaScript yapıları nedeniyle gereksiz görünebilir, ancak bir kullanım durumunu göstermeye yardımcı olur:

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

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

Hem nokta hem de köşeli gösterim, iç içe geçmiş nesneler için beklendiği gibi çalışır:

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

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

Nesne yok etme

Nesne yok etmeyi, bir nesnedeki bir özelliğe erişmek için bir araç olarak da düşünebiliriz, ancak aşağıdaki gibi:

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'

11

Bunu Lodash get kullanarak böyle yapabilirsiniz

_.get(object, 'a[0].b.c');

Derin iç içe nesne aramaları gibi bunun tek seçenek olduğu birçok durum vardır.
Jonathan Kempf

8

GÜNCELLENMİŞ

Aşağıdaki yorumları dikkate aldım ve kabul ettim. Değerlendirmeden kaçınılmalıdır.

Nesnede kök özelliklerine erişmek ile kolayca elde edilir obj[variable], ancak iç içe geçmek bir şeyi zorlaştırır. Zaten yazılı kod yazmamak için kullanmanızı öneririm lodash.get.

Misal

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

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

Lodash get farklı şekillerde kullanılabilir, işte lodash.get belgelerine bağlantı


4
evalMümkün olduğunca kullanmaktan kaçınmak en iyisidir . stackoverflow.com/questions/86513/…
Luke

8
evalÖzelliklere erişim kadar önemsiz bir şey kullanmak , aşırıya kaçar ve hiçbir koşulda tavsiye edilemez. "Sorun" nedir? obj['nested']['test']çok iyi çalışır ve kodu dizelere yerleştirmenizi gerektirmez.
Kyll

3
eval üç kat daha yavaş veya daha fazla, ben yeni başlayanlar için tavsiye etmem çünkü onlara kötü alışkanlıklar öğretebilir. Ben kullanıyorum obj['nested']['value']- çocukları hatırlayın, eval kötülüktür!
jaggedsoft

1
@Luke Artık Lodash'ı _.getmasaya getirmek isteyen tek kişi o. Bence bu cevap şimdi aşağı oy yerine yukarı oy hak ediyor. Aşırı olabilir, ama var olduğunu bilmek güzel.
Emile Bergeron

1
Bunun için lodash'ı tanıttığınız için teşekkür ederiz. Buraya google tarafından bir nesnenin derinliklerinde bir değer ayarlamak için bir yöntem arıyor ve _.set yöntemini kullanmıştım (bu yukarıdakiyle aynıdır ancak ayarlanacak değerin ekstra tartışmasıyla).
TPHughes

5

Özelliğe dinamik olarak erişmeniz gerektiğinde, özelliğe "değil" erişmek için köşeli parantez kullanmanız gerekir. operatör
Sözdizimi: nesne [uygunluk}

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])


4

Düşündüğüm bir davaya rastladım , bu diğer işlevinde adres dizisi ve ekrana gelen arama yapmak başka işleve veri olarak bir nesne özelliğinin "adresi" geçmek istediğini ve (AJAX ile) nesnesini doldurmak. Ben dizi akrobasi yapmadan nokta gösterimi kullanamadı bu yüzden bir dizi yerine geçmek güzel olabilir düşündüm. Yine de farklı bir şey yaptım ama bu yazı ile ilgili görünüyordu.

İşte veri istediğim gibi bir dil dosyası nesnesinin bir örneği:

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

Böyle bir diziyi geçmek istedim: ["audioPlayer", "kontroller", "dur"] dil metnine erişmek için, "bu durumda" dur.

"En az belirli" (ilk) adres parametresini arar ve döndürülen nesneyi kendisine yeniden atar bu küçük işlevi oluşturdu. Ardından, varsa en sonraki adres parametresini aramaya hazırdır.

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

kullanımı:

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

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

2

Bu işleve de parametreler iletmeniz gerektiğinde ilginç hale gelir.

Kod 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

1

ES5 // Derin İç İçe Değişkenleri Kontrol Etme

Bu basit kod parçası, her değişkeni yol boyunca kontrol etmek zorunda kalmadan derin iç içe değişken / değer varlığını kontrol edebilir ...

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

Ör. - derin yuvalanmış bir nesne dizisi:

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

Onun yerine :

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

Şimdi yapabiliriz:

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

Şerefe!


1
Çözüm eval kullanmaksa, bir milyon problem daha yarattınız.
Rodrigo Leite

@RodrigoLeite tamam, bu yüzden en az bir tane vermek sorun olmaz ...


1
@RodrigoLeite Ben okudum ve Functionbunun yerine kullanmak için çözümü güncelledim

0

Bir süre önce bu konuda tekrarlanan bir soru sordum ve aşırı araştırmadan sonra ve burada olması gereken çok fazla bilgi eksik olduğunu gördüm, bu eski yazıya eklemek için değerli bir şeyim olduğunu hissediyorum.

  • Öncelikle, bir özelliğin değerini elde etmenin ve onu dinamik bir Değişkende saklamanın birkaç yolu olduğunu belirtmek istiyorum. IMHO'nun ilk en popüler ve en kolay yolu:
let properyValue = element.style['enter-a-property'];

Ancak, stil sayfaları aracılığıyla atanan özellik değerleri üzerinde çalışmadığından nadiren bu rotaya giderim. Size bir örnek vermek gerekirse, biraz sahte kodla göstereceğim.

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

Yukarıdaki kod örneğini kullanarak; 'elem' değişkeninde depolanan div öğesinin width özelliği bir CSS stil sayfasında stilize edilmişse ve HTML etiketinin içinde biçimlendirilmemişse, kuşkusuz içinde depolanmış tanımsız bir dönüş değeri elde edersiniz cssProp değişkeni. Tanımlanmamış değer, doğru değeri elde etmek için, bir CSS Stil Sayfası içinde yazılan kodun değeri almak için sırayla hesaplanması gerektiğinden oluşur; değeri stil sayfasında yer alan özelliğin değerini hesaplayacak bir yöntem kullanmalısınız.

  • Bundan böyle getComputedStyle () yöntemi!
function getCssProp(){
  let ele = document.getElementById("test");
  let cssProp = window.getComputedStyle(ele,null).getPropertyValue("width");
}

W3Schools getComputedValue Doc Bu iyi bir örnek verir ve onunla oynamanıza izin verir, ancak bu bağlantı Mozilla CSS getComputedValue dokümanı getComputedValue işlevinden ayrıntılı olarak bahseder ve bu konuda tamamen net olmayan herhangi bir istekli geliştirici tarafından okunmalıdır.

  • Yan not olarak, getComputedValue yöntemi yalnızca alır, ayarlanmaz. Bu, açık bir şekilde önemli bir dezavantajdır, ancak standart Javascript olmasa da, CSS stil sayfalarından alınan ve değerleri ayarlayan bir yöntem vardır. JQuery yöntemi ...
$(selector).css(property,value)

... alır ve ayarlanır. Kullandığım şey, tek dezavantajı JQuery'yi tanımanızdır, ancak bu dürüst olmak gerekirse, her Javascript Geliştiricisinin JQuery'yi öğrenmesi gereken çok iyi nedenlerden biridir, sadece hayatı kolaylaştırır ve bunun gibi yöntemler sunar, standart Javascript ile kullanılamaz. Umarım bu birine yardımcı olur !!!


0

Yuvalanmış bir değişkenin değerini ayarlamak isteyen herkes için, nasıl yapılacağı aşağıda açıklanmıştır:

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

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

Ayrıca, bir değer almak istiyorsanız belgeler: https://lodash.com/docs/4.17.15#get



-4
const something = { bar: "Foobar!" };
const foo = 'bar';

something[\`${foo}\`];

7
Bunu neden dünyada yapasın ki? Sizin foozaten bir dize, yani `${foo}`tam olarak aynı olduğunu foo. (Ayrıca, kodunuzun oraya ait olmayan bazı ters eğik çizgiler var gibi görünüyor. Ancak sözdizimi hatasını düzeltseniz bile yine de anlamsız olurdu.)
Ilmari Karonen
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.