Hazırlıklar
JavaScript'in birden fazla değer içerebilecek tek bir veri türü vardır: Nesne . Bir Dizi nesnenin özel bir şeklidir.
(Düz) Nesneler şu şekildedir:
{key: value, key: value, ...}
Diziler şu şekildedir
[value, value, ...]
Hem diziler hem de nesneler bir key -> value
yapı ortaya çıkarır . Bir dizideki anahtarlar sayısal olmalıdır, oysa herhangi bir dize nesnelerde anahtar olarak kullanılabilir. Anahtar / değer çiftlerine "özellikler" de denir .
Özelliklere nokta gösterimi kullanılarak erişilebilir
const value = obj.someProperty;
veya braket notasyonu , özellik adı geçerli bir JavaScript olmazdı eğer tanımlayıcı adını [Spec] veya adı değişkenin değerdir:
// the space is not a valid character in identifier names
const value = obj["some Property"];
// property name as variable
const name = "some Property";
const value = obj[name];
Bu nedenle, dizi öğelerine yalnızca köşeli ayraç gösterimi kullanılarak erişilebilir:
const value = arr[5]; // arr.5 would be a syntax error
// property name / index as variable
const x = 5;
const value = arr[x];
Bekle ... JSON ne olacak?
JSON, XML, YAML, CSV ve diğerleri gibi verilerin metinsel bir temsilidir. Bu tür verilerle çalışmak için öncelikle JavaScript veri türlerine, yani dizilere ve nesnelere (ve bunlarla nasıl çalışılacağı açıklanmıştır) dönüştürülmelidir. JavaScript'te ayrıştırma JSON sorusunda JSON nasıl ayrıştırılır ? .
İlave okuma materyalleri
Dizilere ve nesnelere nasıl erişileceği temel JavaScript bilgisidir ve bu nedenle MDN JavaScript Kılavuzunu , özellikle bölümleri okumanız önerilir.
İç içe veri yapılarına erişme
Yuvalanmış veri yapısı, diğer dizilere veya nesnelere başvuran bir dizi veya nesnedir, yani değerleri diziler veya nesnelerdir. Bu tür yapılara art arda nokta veya köşeli parantez notasyonu uygulanarak erişilebilir.
İşte bir örnek:
const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
name
İkinci öğeye erişmek istediğimizi varsayalım .
Bunu adım adım nasıl yapabiliriz:
Gördüğümüz gibi data
bir nesne, dolayısıyla nokta gösterimini kullanarak özelliklerine erişebiliyoruz. items
Aşağıdaki gibi özellik erişilen:
data.items
Değer bir dizidir, ikinci öğesine erişmek için parantez notasyonu kullanmamız gerekir:
data.items[1]
Bu değer bir nesnedir ve name
özelliğe erişmek için nokta gösterimini tekrar kullanırız . Sonuçta:
const item_name = data.items[1].name;
Alternatif olarak, özellikle ad nokta gösterimi kullanımı için geçersiz kılacak karakterler içeriyorsa, özelliklerin herhangi biri için köşeli ayraç gösterimini kullanabilirdik:
const item_name = data['items'][1]['name'];
Bir mülke erişmeye çalışıyorum ama sadece undefined
geri dönüyorum?
Çoğu zaman undefined
, nesne / dizi bu ada sahip bir özelliğe sahip değildir.
const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined
Nesnenin / dizinin yapısını kullanın console.log
veya console.dir
denetleyin. Erişmeye çalıştığınız özellik aslında iç içe geçmiş bir nesnede / dizide tanımlanmış olabilir.
console.log(foo.bar.baz); // 42
Özellik adları dinamikse ve bunları önceden bilmiyorsam ne olur?
Özelliği adlarının bilinmediği ya da bir nesnenin bütün özelliklerine ulaşmak için / bir dizi elemanları, kullanabiliriz for...in
[MDN] nesneler için döngü ve for
[MDN] tüm özellikleri / elemanları üzerinde ilerlerken diziler için döngü.
Nesneler
Öğesinin tüm özelliklerini data
yinelemek için, nesne üzerinde şöyle yineleme yapabiliriz :
for (const prop in data) {
// `prop` contains the name of each property, i.e. `'code'` or `'items'`
// consequently, `data[prop]` refers to the value of each property, i.e.
// either `42` or the array
}
Nesnenin nereden geldiğine (ve ne yapmak istediğinize) bağlı olarak, her yinelemede özelliğin gerçekten nesnenin bir özelliği mi yoksa miras alınan bir özellik mi olduğunu test etmeniz gerekebilir. Bunu Object#hasOwnProperty
[MDN] ile yapabilirsiniz .
İçin alternatif olarak for...in
birlikte hasOwnProperty
kullanabileceğiniz Object.keys
[MDN] bir olsun özellik adları dizisi :
Object.keys(data).forEach(function(prop) {
// `prop` is the property name
// `data[prop]` is the property value
});
Diziler
data.items
Dizinin tüm öğelerini yinelemek için bir for
döngü kullanırız :
for(let i = 0, l = data.items.length; i < l; i++) {
// `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration
// we can access the next element in the array with `data.items[i]`, example:
//
// var obj = data.items[i];
//
// Since each element is an object (in our example),
// we can now access the objects properties with `obj.id` and `obj.name`.
// We could also use `data.items[i].id`.
}
for...in
Diziler üzerinde yineleme yapmak için de kullanılabilir , ancak bundan kaçınılması gereken nedenler vardır: Neden 'for (listedeki öğe)' dizisi JavaScript'te kötü uygulama olarak kabul edilir? .
ECMAScript 5'in artan tarayıcı desteği ile dizi yöntemi forEach
[MDN] de ilginç bir alternatif haline geliyor:
data.items.forEach(function(value, index, array) {
// The callback is executed for each element in the array.
// `value` is the element itself (equivalent to `array[index]`)
// `index` will be the index of the element in the array
// `array` is a reference to the array itself (i.e. `data.items` in this case)
});
ES2015'i (ES6) destekleyen ortamlarda , yalnızca diziler için değil , aynı zamanda yinelenebilirler için de çalışan [MDN] döngüsünü kullanabilirsiniz :for...of
for (const item of data.items) {
// `item` is the array element, **not** the index
}
Her yinelemede, for...of
doğrudan bize yinelemenin bir sonraki öğesini verir, erişmek veya kullanmak için bir "dizin" yoktur.
Veri yapısının "derinliği" benim için bilinmiyorsa ne olur?
Bilinmeyen anahtarlara ek olarak, veri yapısının "derinliği" (yani kaç tane iç içe nesne) sahip olduğu da bilinmiyor olabilir. Derin yuvalanmış özelliklere nasıl erişilir genellikle veri yapısına bağlıdır.
Ancak veri yapısı, örneğin ikili bir ağacın temsili gibi yinelenen desenler içeriyorsa, çözüm tipik olarak veri yapısının her bir seviyesine tekrar tekrar [Wikipedia] erişimini içerir.
İşte bir ikili ağacın ilk yaprak düğümünü almak için bir örnek:
function getLeaf(node) {
if (node.leftChild) {
return getLeaf(node.leftChild); // <- recursive call
}
else if (node.rightChild) {
return getLeaf(node.rightChild); // <- recursive call
}
else { // node must be a leaf node
return node;
}
}
const first_leaf = getLeaf(root);
const root = {
leftChild: {
leftChild: {
leftChild: null,
rightChild: null,
data: 42
},
rightChild: {
leftChild: null,
rightChild: null,
data: 5
}
},
rightChild: {
leftChild: {
leftChild: null,
rightChild: null,
data: 6
},
rightChild: {
leftChild: null,
rightChild: null,
data: 7
}
}
};
function getLeaf(node) {
if (node.leftChild) {
return getLeaf(node.leftChild);
} else if (node.rightChild) {
return getLeaf(node.rightChild);
} else { // node must be a leaf node
return node;
}
}
console.log(getLeaf(root).data);
Bilinmeyen tuşları ve derinliği olan bir iç içe veri yapısına erişmenin daha genel bir yolu, değerin türünü sınamak ve buna göre hareket etmektir.
İç içe veri yapısı içindeki tüm ilkel değerleri bir diziye ekleyen bir örnek (herhangi bir işlev içermediği varsayılarak). Bir nesneyle (veya diziyle) karşılaşırsak toArray
, o değere tekrar çağırırız (özyinelemeli çağrı).
function toArray(obj) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(toArray(value)); // <- recursive call
}
else {
result.push(value);
}
}
return result;
}
const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
function toArray(obj) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(toArray(value));
} else {
result.push(value);
}
}
return result;
}
console.log(toArray(data));
Yardımcılar
Karmaşık bir nesnenin veya dizinin yapısı mutlaka belli olmadığından, nasıl ilerleyeceğine karar vermek için her adımdaki değeri inceleyebiliriz. console.log
[MDN] ve console.dir
[MDN] bunu yapmamıza yardımcı oluyor. Örneğin (Chrome konsolunun çıktısı):
> console.log(data.items)
[ Object, Object ]
Burada data.items
bunun her iki nesne olan iki öğeden oluşan bir dizi olduğunu görüyoruz . Chrome konsolunda nesneler hemen genişletilebilir ve denetlenebilir.
> console.log(data.items[1])
Object
id: 2
name: "bar"
__proto__: Object
Bu bize bunun data.items[1]
bir nesne olduğunu söyler ve onu genişlettikten sonra üç özelliği olduğunu görürüz id
, name
ve __proto__
. İkincisi, nesnenin prototip zinciri için kullanılan dahili bir özelliktir. Yine de, prototip zinciri ve miras bu cevabın kapsamı dışındadır.