javascript - Nokta notasyonu stringi kullanarak nesne alt özelliklerine erişim


Geçici olarak çok basit görünüyor bir JavaScript problemi ile takıldım, ama belki de doğru arama anahtar kelimelerini kaçırıyorum!

Diyelim ki bir nesnemiz var

var r = { a:1, b: {b1:11, b2: 99}};

99'a erişmenin birkaç yolu vardır:

r.b.b2
r['b']['b2']

İstediğim şey bir string tanımlayabilmek

var s = "b.b2";

ve sonra 99'u kullanarak erişin

r.s or r[s] //(which of course won't work)

Bunun için bir yol, noktada bölünmüş bir string üzerinde çalışan ve belki de özelliği özyinelemeli/iteratif olarak alan bir fonksiyon yazmaktır. Ama daha basit/daha verimli bir yol var mı? Burada jQuery API’lerinden herhangi biri faydalı olur mu?

Cevap #1

Bir süre önce yazdığım saf bir fonksiyon işte, ama temel nesne özellikleri için çalışıyor:

function getDescendantProp(obj, desc) {
    var arr = desc.split(".");
    while(arr.length && (obj = obj[arr.shift()]));
    return obj;
}

console.log(getDescendantProp(r, "b.b2"));
//-> 99

Buna "izin ver" dizi indeks erişimini uzatan yanıtlar olsa da, bu aslında gerekli değil çünkü bu yöntemle yalnızca sayısal indeksleri nokta gösterimi kullanarak belirtebilirsiniz:

getDescendantProp({ a: [ 1, 2, 3 ] }, 'a.2');
//-> 3

Cevap #2

split ve reduce ile nesneyi initalValue olarak geçirirken

Güncelleme (TeChn4K tarafından yapılan yoruma teşekkürler)

ES6 sözdizimi ile, bu daha da kısadır

var r = { a:1, b: {b1:11, b2: 99}};
var s = "b.b2";

var value = s.split('.').reduce((a, b) => a[b], r);

console.log(value);

Eski sürüm

var r = { a:1, b: {b1:11, b2: 99}};
var s = "b.b2";

var value = s.split('.').reduce(function(a, b) {
  return a[b];
}, r);

console.log(value);

Cevap #3

Lodash get() ve set() yöntemlerini kullanabilirsiniz.

Almak

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

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

Kurulum

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

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

Cevap #4

Senin senaryonda, hedeflediğin tüm dizi değişkenini bir string içine koyman mümkünse, eval() fonksiyonunu kullanabilirsin.

var r = { a:1, b: {b1:11, b2: 99}};
var s = "r.b.b2";
alert(eval(s)); // 99

İnsanların dehşet içinde sarsıldığını hissedebiliyorum

Cevap #5

@JohnB'nin cevabını genişleterek, ben de bir setter değeri ekledim. Plunkr'a göz atın

http://plnkr.co/edit/lo0thC?p=preview

function getSetDescendantProp(obj, desc, value) {
  var arr = desc ? desc.split(".") : [];

  while (arr.length && obj) {
    var comp = arr.shift();
    var match = new RegExp("(.+)\\[([0-9]*)\\]").exec(comp);

    // handle arrays
    if ((match !== null) && (match.length == 3)) {
      var arrayData = {
        arrName: match[1],
        arrIndex: match[2]
      };
      if (obj[arrayData.arrName] !== undefined) {
        if (typeof value !== 'undefined' && arr.length === 0) {
          obj[arrayData.arrName][arrayData.arrIndex] = value;
        }
        obj = obj[arrayData.arrName][arrayData.arrIndex];
      } else {
        obj = undefined;
      }

      continue;
    }

    // handle regular things
    if (typeof value !== 'undefined') {
      if (obj[comp] === undefined) {
        obj[comp] = {};
      }

      if (arr.length === 0) {
        obj[comp] = value;
      }
    }

    obj = obj[comp];
  }

  return obj;
}

İlgili makaleler