IlmHamroh
JavaScript Full-stack/10-qism. JavaScript chuqur15/65-dars19 daqiqa
Mundarija (36)

JavaScript Object metodlari: assign, entries, fromEntries, hasOwn, is va boshqalar — to'liq sharh

Qisqacha: Object da 23 ta statik metod bor va ular olti guruhga bo'linadi: ko'rish (keys, entries, getOwnPropertyNames), aylantirish (fromEntries, groupBy), nusxalash (assign), tekshirish (hasOwn, is), himoya (freeze, seal) va deskriptor/prototip. Eng ko'p ishlatiladigan naqsh — Object.fromEntries(Object.entries(obj).map(...)): obyektni massivga aylantirib, massiv metodlari bilan ishlab, qaytarib obyektga yig'ish.

Bu darsda

  • Object ning barcha statik metodlarini olti guruhga ajratib, har biri qachon kerakligini ayta olasiz.
  • entries → map/filter → fromEntries naqshi bilan obyektni o'zgartira olasiz.
  • Object.assign va spread farqini (birinchi argument o'zgarishi, setter'lar) bilasiz.
  • Nega hasOwnProperty o'rniga Object.hasOwn ishlatish kerakligini ko'rsata olasiz.
  • vazifalar ga noma'lum filtr nomidan himoya qo'shasiz.

Oldin bilishingiz kerak: Obyektni himoyalash, Obyekt bo'ylab yurish, Obyekt: kalit-qiymat juftliklari, Tenglik va Object.is, Guruhlash: Object.groupBy.

1. Nega bu kerak?

Oxirgi uch darsda Object ning ko'p yangi metodlarini oldik: deskriptorlar, freeze, seal. 08-qismda esa keys, values, entries, hasOwn ni o'rgangan edik. Hammasi Object. bilan boshlanadi. Ular ko'paygan sari "qaysi biri nima qilardi?" degan savol tug'iladi.

Hayotdan o'xshatish: ustaning asboblar qutisi. Yangi usta asboblarni bitta qopga solib yuradi va har safar kerakligini topish uchun hammasini to'kib tashlaydi. Tajribali usta esa qutini bo'limlarga ajratgan: o'lchash, kesish, mahkamlash. Asbobning o'zini emas, qaysi bo'limda turishini eslaydi.

Bu dars — o'sha bo'limlarga ajratilgan quti. Avval to'liq xaritani ko'ramiz. Keyin hali o'rganilmagan yoki chala o'rganilgan metodlarni ochamiz: assign ning tuzoqlari, entries/fromEntries naqshi, getOwnPropertyNames, va nega hasOwnProperty eskirganini.

2. To'liq xarita

2.1 Olti bo'lim

Node 24 dagi Object ning barcha statik metodlari — 23 ta. Ularni vazifasi bo'yicha guruhlaymiz:

Bo'lim Metodlar Qayerda
Ko'rish keys, values, entries, getOwnPropertyNames, getOwnPropertySymbols Obyekt bo'ylab yurish, shu dars
Yasash va aylantirish fromEntries, groupBy, create Guruhlash, Object.create
Nusxalash assign shu dars
Tekshirish hasOwn, is Tenglik, shu dars
Bo'lim Metodlar Qayerda
Himoya freeze, isFrozen, seal, isSealed, preventExtensions, isExtensible Himoyalash
Deskriptor defineProperty, defineProperties, getOwnPropertyDescriptor, getOwnPropertyDescriptors Deskriptorlar
Prototip getPrototypeOf, setPrototypeOf Prototip

Jadval telefonda sig'ishi uchun ikkiga bo'lingan. Prototip va create — Prototip va prototip zanjiri darsidan boshlab; hozir bilish shart emas. Qolgan hammasini bilasiz yoki bugun o'rganasiz.

Shu xaritani sxemada ko'ring — yodda saqlash uchun bo'lim nomlari yetarli:

flowchart LR
  O(("Object.*")) --> K["Ko'rish"]
  O --> Y["Yasash / aylantirish"]
  O --> N["Nusxalash"]
  O --> T["Tekshirish"]
  O --> H["Himoya"]
  O --> D["Deskriptor va prototip"]

2.2 Nega obj.keys() emas, Object.keys(obj)?

Obyekt bo'ylab yurish darsida aytgan edik: bu metodlar sizning obyektingizda emas, Object ning o'zida turadi. Sababi bor. Agar keys har obyektning metodi bo'lsa, { keys: "kalitlar ro'yxati" } kabi obyektda u buzilardi — ma'lumot metod nomini egallab olardi. Object.keys(x) esa har qanday obyekt bilan, uning ichida nima bo'lishidan qat'i nazar, ishlaydi. Bu fikr «Tekshirish» bo'limida yana kerak bo'ladi.

2.3 Statik metodlar va har obyektdagi metodlar

Bitta chalkashlikni oldindan yechamiz. Object.keys — statik metod (static method): u Object ning o'zida turadi va obyektni argument sifatida oladi. Xuddi bozordagi umumiy tarozi kabi: u hech bir sotuvchiniki emas, har kim o'z mahsulotini olib kelib tortadi. Lekin har oddiy obyektda o'zi chaqira oladigan bir nechta metod ham bor: toString, valueOf, hasOwnProperty. Ular sizning obyektingizda yozilmagan — umumiy "ota" obyektdan meros keladi:

js
const taom = { nom: "Osh" };

console.log(taom.toString()); // [object Object]
console.log(Object.hasOwn(taom, "toString")); // false
console.log("toString" in taom); // true

[object Object] — tanish satr: reduce darsida boshlang'ich qiymat unutilganda aynan shu chiqqan edi — obyekt satrga aylantirilganda toString ishlaydi. toString obyektning o'zida yo'q (hasOwn — false), lekin in uni ko'radi, chunki in merosni ham hisobga oladi. Bu farq darsning «Vazifalar qadami» da juda kerak bo'ladi. Meros qanday ishlashini — "ota" obyekt qayerda turishini — Prototip va prototip zanjiri darsida ochamiz.

Tekshirib ko'ring: Xaritadan toping: obyektni muzlatilganmi deb tekshiradigan metod qaysi bo'limda? Obyektni guruhlarga ajratadigan-chi?

Javob

Object.isFrozen — «Himoya» bo'limida (u tekshiradi, lekin himoya bilan bog'liq). Object.groupBy — «Yasash va aylantirish»: u massivdan yangi obyekt yasaydi. Bo'limlar — vazifa bo'yicha, metod nomidagi so'z bo'yicha emas.

3. Ko'rish: qaysi metod nimani ko'radi

3.1 getOwnPropertyNames

Object.keys faqat sanaladigan kalitlarni beradi (Xususiyat deskriptorlari). Object.getOwnPropertyNames esa — obyektning barcha o'z kalitlarini, sanalmaydiganlarini ham:

js
const narxlar = ["osh"];

console.log(Object.keys(narxlar)); // [ '0' ]
console.log(Object.getOwnPropertyNames(narxlar)); // [ '0', 'length' ]
console.log(Object.keys(Math).length); // 0
console.log(Object.getOwnPropertyNames(Math).length); // 44

Math da Object.keys hech narsa topmadi — uning hamma xususiyati (PI, max, round...) sanalmaydigan. getOwnPropertyNames esa 44 tasini topdi. Bu metod ko'pincha "obyekt ichida nima bor?" deb o'rganish uchun kerak — masalan, yangi kutubxona obyektini konsolda tekshirganda.

Darsning boshidagi "23 ta metod" sonini aynan shu metod bilan sanadik. Object ning o'zi ham obyekt — uning ichiga qaraymiz:

js
const nomlar = Object.getOwnPropertyNames(Object);
const metodlar = nomlar.filter(
  (nom) => typeof Object[nom] === "function",
);

console.log(metodlar.length); // 23
console.log(nomlar.filter((nom) => !metodlar.includes(nom)));

Konsolda:

text
23
[ 'length', 'name', 'prototype' ]

Object[nom] — kalit o'zgaruvchida bo'lgani uchun kvadrat qavs (Obyekt: kalit-qiymat juftliklari). Funksiya bo'lmagan uchta xususiyat — Object funksiya ekani bilan bog'liq texnik qismlar. Object.keys(Object) esa bo'sh massiv qaytarardi: bularning hammasi sanalmaydigan. Yangi muhitda (masalan, keyingi Node versiyasida) metod qo'shilsa, bu kod uni ham topadi — xaritani o'zingiz yangilay olasiz.

3.2 getOwnPropertySymbols

Kalit faqat satr emas, symbol ham bo'lishi mumkin — hech qachon boshqa kalit bilan to'qnashmaydigan maxsus qiymat. Uni Symbol darsida o'rganamiz, hozir bilish shart emas. Symbol kalitlarni na keys, na getOwnPropertyNames ko'rsatadi — ular uchun alohida Object.getOwnPropertySymbols bor.

3.3 Uch metod bir jadvalda

Metod Sanalmaydigan Symbol Meros
Object.keys yo'q yo'q yo'q
Object.getOwnPropertyNames ha yo'q yo'q
Object.getOwnPropertySymbols ha faqat symbol yo'q

Uchalasi ham faqat o'z kalitlarini beradi, meros kalitlar (toString kabi) hech birida yo'q. values va entries — keys bilan bir xil qoidada ishlaydi.

Tekshirib ko'ring: Object.defineProperty bilan yaratilgan, faqat value berilgan xususiyat uchta metoddan qaysi birida ko'rinadi?

Javob

Faqat Object.getOwnPropertyNames da. defineProperty da yozilmagan enumerable — false (Xususiyat deskriptorlari), shuning uchun Object.keys uni bermaydi. Kalit satr — symbol emas, demak getOwnPropertySymbols da ham yo'q.

4. entries → map → fromEntries

4.1 Naqsh

Obyektda map yo'q, filter yo'q. Massivda esa bor. Shuning uchun obyektni o'zgartirishning eng mashhur yo'li — uch qadamli "aylanma yo'l":

  1. Object.entries(obj) — obyekt → [kalit, qiymat] juftliklari massivi.
  2. Massiv metodlari — map, filter, toSorted.
  3. Object.fromEntries(...) — juftliklar massivi → yangi obyekt.

Kechki aksiya: barcha narxlarga 10% chegirma.

js
const menyu = { osh: 35000, lagmon: 28000, manti: 30000, choy: 5000 };

const aksiya = Object.fromEntries(
  Object.entries(menyu).map(([nom, narx]) => [nom, narx * 0.9]),
);

console.log(aksiya);
console.log(menyu.osh);

Konsolda:

text
{ osh: 31500, lagmon: 25200, manti: 27000, choy: 4500 }
35000

map callback'i massiv destructuring bilan juftlikni nom va narx ga ajratdi va yangi juftlik qaytardi. fromEntries ularni yig'di. Asl menyu o'zgarmadi — biz yangi obyekt yasadik. (Bu yerda natijalar butun chiqdi; kasrli natijada Pul va aniq hisob-kitob darsidagi Math.round kerak bo'ladi.)

Sxemada qadamlarni kuzating — obyekt massivga aylanadi, o'zgaradi va yana obyektga qaytadi:

flowchart LR
  A["{ osh: 35000 }"] -- "Object.entries" --> B["[['osh', 35000]]"]
  B -- "map / filter" --> C["[['osh', 31500]]"]
  C -- "Object.fromEntries" --> D["{ osh: 31500 }"]

4.2 Filtrlash va kalitlarni o'zgartirish

Xuddi shu naqsh filter bilan — 30 000 dan arzon taomlar:

js
const menyu = { osh: 35000, lagmon: 28000, manti: 30000, choy: 5000 };

const arzon = Object.fromEntries(
  Object.entries(menyu).filter(([, narx]) => narx < 30000),
);

console.log(arzon); // { lagmon: 28000, choy: 5000 }

[, narx] — birinchi elementni (nomni) o'tkazib yuborish: bizga faqat narx kerak.

Qiymatni emas, kalitni o'zgartirish ham mumkin. Masalan, ma'lumotni inglizcha nomli maydonlar kutadigan xizmatga yuborish kerak:

js
const mehmon = { ism: "Malika", telefon: "+998 90 000 00 00" };
const nomlar = { ism: "name", telefon: "phone" };

const tashqi = Object.fromEntries(
  Object.entries(mehmon).map(([kalit, qiymat]) => [
    nomlar[kalit],
    qiymat,
  ]),
);

console.log(tashqi); // { name: 'Malika', phone: '+998 90 000 00 00' }

Bu yerda nomlar — "lug'at": o'zbekcha kalit → inglizcha kalit.

4.3 Obyektni qiymat bo'yicha tartiblash

Obyektda sort ham yo'q. Lekin juftliklar massivini tartiblash mumkin — toSorted bilan. Menyuni arzondan qimmatga:

js
const menyu = { osh: 35000, lagmon: 28000, manti: 30000, choy: 5000 };

const juftlar = Object.entries(menyu).toSorted(
  ([, a], [, b]) => a - b,
);
const tartibli = Object.fromEntries(juftlar);

console.log(tartibli);
console.log(juftlar.at(-1));

Konsolda:

text
{ choy: 5000, lagmon: 28000, manti: 30000, osh: 35000 }
[ 'osh', 35000 ]

Taqqoslash funksiyasi juftlikni destructuring bilan ochadi va faqat narxlarni solishtiradi (sort va taqqoslash funksiyasi). fromEntries juftliklar tartibini saqlaydi — natijaviy obyektda kalitlar arzondan qimmatga turadi. juftlar.at(-1) — oxirgisi, ya'ni eng qimmat taom.

Bitta istisno bor. Obyekt bo'ylab yurish darsidagi qoida: butun songa o'xshash kalitlar ("1", "25") obyektda har doim o'sish tartibida turadi, qanday qo'shilganidan qat'i nazar. Shuning uchun kalitlari id raqamlari bo'lgan obyektni bu usul bilan tartiblab bo'lmaydi — tartib kerak bo'lsa, natijani massivligicha qoldiring.

Maslahat: Object.fromEntries faqat massiv bilan emas, har qanday juftliklar ro'yxati bilan ishlaydi. Brauzerda eng foydali holat — forma: Object.fromEntries(new FormData(forma)) butun formani bitta qatorda { ism: "...", telefon: "..." } obyektiga aylantiradi (FormData).

Tekshirib ko'ring: Object.fromEntries([["osh", 1], ["osh", 2]]) nima qaytaradi?

Javob

{ osh: 2 }. Bitta kalit ikki marta kelsa, oxirgisi g'olib — xuddi obyektga ikki marta yozgandek: o.osh = 1; o.osh = 2;. Takroriy kalitlar haqida xato ham, ogohlantirish ham yo'q.

5. Object.assign

5.1 Nima qiladi

Sayoz va chuqur nusxalash darsida Object.assign ni spread'ning "eski akasi" sifatida ko'rgan edik. Imzosi:

js
Object.assign(nishon, manba1, manba2, ...);

U har manbaning sanaladigan o'z xususiyatlarini nishonga yozadi va nishonning o'zini qaytaradi. Keyingi manba oldingisining bir xil kalitini bosib ketadi:

js
const asosiy = { til: "uz", chek: true };
const natija = Object.assign({}, asosiy, { chek: false });

console.log(natija); // { til: 'uz', chek: false }

Birinchi argument — bo'sh {}. Shuning uchun natija yangi obyekt. Bu yozuv { ...a, ...b } bilan deyarli bir xil. Lekin "deyarli" so'zida ikki tuzoq yashiringan.

5.2 Tuzoq 1: birinchi argument o'zgaradi

js
const STANDART = { til: "uz", valyuta: "so'm", chek: true };

const sozlama = Object.assign(STANDART, { chek: false });

console.log(sozlama === STANDART); // true
console.log(STANDART.chek); // false

{} unutildi — va assign standart sozlamalarning o'zini o'zgartirdi. Endi dasturning boshqa joylari ham chek: false ni ko'radi. Natija ham yangi obyekt emas — STANDART ning o'zi.

Qoida: assign dan nusxa uchun foydalansangiz, birinchi argument doim yangi {} bo'lsin. Yoki spread yozing — u bu xatoga yo'l qo'ymaydi: { ...STANDART, chek: false }. Agar STANDART muzlatilgan bo'lsa (Obyektni himoyalash), xatoli assign darhol TypeError berardi — freeze ning foydasi yana bir bor.

5.3 Tuzoq 2: setter'lar

assign nishonga oddiy tayinlash bilan yozadi: nishon.kalit = qiymat. Demak, nishonda setter bo'lsa — u chaqiriladi. Spread esa yangi obyektda xususiyatni to'g'ridan-to'g'ri yaratadi — setter'ga e'tibor bermaydi:

js
const mehmon = {
  _telefon: "",
  get telefon() {
    return this._telefon;
  },
  set telefon(matn) {
    this._telefon = matn.replaceAll(" ", "");
  },
};

Object.assign(mehmon, { telefon: "+998 90 000 00 00" });
console.log(mehmon.telefon); // +998900000000

const nusxa = { ...mehmon, telefon: "+998 90 111 11 11" };
console.log(nusxa.telefon); // +998 90 111 11 11

assign Getter va setter darsidagi tozalovchi setter'dan o'tdi — bo'sh joylar olib tashlandi. Spread esa nusxada telefon ni oddiy xususiyat qilib yaratdi: setter yo'q, tozalash yo'q. Ko'pincha bu farq sezilmaydi. Lekin setter'li obyektga ma'lumot "quyganda" — assign kerak.

Object.assign(nishon, ...) { ...a, ...b }
Natija nishonning o'zi har doim yangi obyekt
Nishondagi setter chaqiriladi —
Manbadagi getter chaqiriladi chaqiriladi
null/undefined manba o'tkazib yuboriladi o'tkazib yuboriladi

5.4 Manbadagi getter: qiymat ko'chadi

Xususiyat deskriptorlari darsida savol qoldirgan edik: Object.assign getter'ni qanday ko'chiradi? Javob — spread kabi: getter chaqiriladi, natijasi oddiy qiymat bo'lib yoziladi.

js
const savat = {
  taomlar: [35000],
  get jami() {
    return this.taomlar.reduce((s, n) => s + n, 0);
  },
};

const nusxa = Object.assign({}, savat);
nusxa.taomlar.push(5000);

console.log(nusxa.jami, savat.jami); // 35000 40000
const d = Object.getOwnPropertyDescriptor(nusxa, "jami");
console.log(d.value, d.get); // 35000 undefined

Nusxada jami — value: 35000 li oddiy xususiyat, getter emas. taomlar esa umumiy massiv (sayoz nusxa), shuning uchun push ikkalasiga ham tegdi — lekin nusxadagi jami buni "bilmaydi". Getter'ni saqlab nusxalash — faqat deskriptorlar orqali: Object.defineProperties({}, Object.getOwnPropertyDescriptors(savat)).

Demak, assign ning ikki tomoni bor: nishonda u setter'larni ishga tushiradi, manbada esa getter'larni o'qiydi. Ikkalasida ham u xususiyatlarning "tavsifi" bilan emas, faqat qiymatlari bilan ishlaydi.

Tekshirib ko'ring: const a = { x: 1 }; const b = Object.assign(a, { y: 2 }); — a === b va Object.keys(a) nima?

Javob

true va [ 'x', 'y' ]. assign a ni o'zgartirdi va o'shani qaytardi. b — yangi obyekt emas, a ga ikkinchi nom.

6. Tekshirish: hasOwn va is

6.1 hasOwnProperty ning ikki muammosi

Obyekt: kalit-qiymat juftliklari darsida Object.hasOwn ni o'rgangan va "eski kodda obj.hasOwnProperty("k") uchraydi" degan edik. Endi nega yangi kodda faqat Object.hasOwn yozilishini ko'ramiz.

Birinchi muammo: ba'zi obyektlarda hasOwnProperty umuman yo'q. Guruhlash darsidagi Object.groupBy natijasini eslang:

js
const guruh = Object.groupBy([35000, 5000, 28000], (n) =>
  n > 20000 ? "qimmat" : "arzon",
);

console.log(guruh);
console.log(Object.hasOwn(guruh, "arzon")); // true

Konsolda:

text
[Object: null prototype] { qimmat: [ 35000, 28000 ], arzon: [ 5000 ] }
true

[Object: null prototype] — bu obyekt hech kimdan "meros" olmagan. Oddiy obyektlar toString, hasOwnProperty kabi metodlarni umumiy "ota" obyektdan oladi (Prototip darsida batafsil). Bu obyektda esa ota yo'q — shuning uchun guruh.hasOwnProperty("arzon") TypeError: guruh.hasOwnProperty is not a function beradi. Object.hasOwn esa ishladi.

Ikkinchi muammo: ma'lumot metod nomini egallab olishi mumkin. Foydalanuvchi kiritgan kalitlardan obyekt yasaldi deylik:

js
const izohlar = { hasOwnProperty: "zo'r taom!", osh: "mazali" };

console.log(izohlar.hasOwnProperty("osh"));
text
TypeError: izohlar.hasOwnProperty is not a function

Tarjimasi: "izohlar.hasOwnProperty — funksiya emas". Obyektning o'zida hasOwnProperty degan satr paydo bo'ldi va u meros metodni to'sib qo'ydi. Bu — «Nega obj.keys() emas» bo'limidagi muammoning aynan o'zi. Hujumchi bunday kalitni ataylab yuborib, server kodini "sindirishi" mumkin. Object.hasOwn(izohlar, "osh") esa true qaytaradi — u Object da turadi va obyekt ichidagi narsaga bog'liq emas.

Qoida: har doim Object.hasOwn(obj, "kalit"). obj.hasOwnProperty(...) ni eski kodda ko'rsangiz — ma'nosi bir xil, lekin yangisida yozmang.

6.2 Object.is — eslatma

Tenglik va Object.is darsida Object.is ni === bilan solishtirgan edik. U ikki holatda farq qiladi:

js
console.log(NaN === NaN, Object.is(NaN, NaN)); // false true
console.log(0 === -0, Object.is(0, -0)); // true false

Qolgan barcha holatlarda Object.is va === bir xil. Amalda Object.is ni kamdan-kam qo'lda yozasiz, lekin u ko'p kutubxonalar ichida ishlaydi. Masalan, React (interfeys yasash kutubxonasi — 17-qismda o'rganamiz, hozir bilish shart emas) holat o'zgarganini aynan Object.is bilan tekshiradi — yangi obyekt yasalmasa, havola o'sha-o'sha qoladi va ekran yangilanmaydi. Bu — keyingi darsning asosiy sababi.

Tekshirib ko'ring: [NaN].includes(NaN) va [NaN].indexOf(NaN) nima qaytaradi? Qaysi biri Object.is ga o'xshab ishlaydi?

Javob

true va -1. includes NaN'ni topadi — u Object.is ga yaqin qoida bilan solishtiradi (0 va -0 ni esa teng deb oladi). indexOf esa === ishlatadi, NaN === NaN — false, shuning uchun topolmaydi.

7. Ko'p uchraydigan xatolar

7.1 obj.keys() deb yozish

menyu.keys is not a function. Tuzatish: Object.keys(menyu) — metod Object da.

7.2 Object.assign(standart, ...) — standart buzildi

Birinchi argument o'zgaradi va qaytariladi. Tuzatish: Object.assign({}, standart, ...) yoki { ...standart, ... }.

7.3 fromEntries ga juftlik emas, qiymat qaytarish

Object.entries(m).map(([k, v]) => v * 0.9) — map sonlar massivi qaytaradi, fromEntries esa juftlik kutadi: TypeError: Iterator value 31500 is not an entry object. Tuzatish: [k, v * 0.9] — har doim ikki elementli massiv.

7.4 hasOwnProperty ni obyektning o'zidan chaqirish

Null-prototipli obyektda yoki ma'lumot nom egallaganda — TypeError. Tuzatish: Object.hasOwn.

7.5 Object.keys "hammasini" beradi deb o'ylash

Sanalmaydigan va symbol kalitlar unda yo'q. Tuzatish: obyektni o'rganayotganda — Object.getOwnPropertyNames yoki Object.getOwnPropertyDescriptors.

8. Mashqlar

1-mashq (oson): Narxlarni mingga yaxlitlash

Menyu narxlarini 15% oshiring va minggacha yaxlitlang. Asl menyu o'zgarmasin. Ishora: Math.round(x / 1000) * 1000 (Math obyekti); naqsh — entries → map → fromEntries.

js
const menyu = { osh: 35000, lagmon: 28000, manti: 30000, choy: 5000 };
Yechim
js
const menyu = { osh: 35000, lagmon: 28000, manti: 30000, choy: 5000 };

const yangi = Object.fromEntries(
  Object.entries(menyu).map(([nom, narx]) => [
    nom,
    Math.round((narx * 1.15) / 1000) * 1000,
  ]),
);

console.log(yangi);
console.log(menyu.osh);

Konsolda:

text
{ osh: 40000, lagmon: 32000, manti: 35000, choy: 6000 }
35000

35 000 × 1,15 = 40 250 → 40 000. Choy: 5 750 → 6 000. Naqsh uch qadam: juftliklar, har juftlikdan yangi juftlik, qaytarib obyekt.

2-mashq (o'rta): Sozlamalarni birlashtirish

sozlamaYasa(foydalanuvchi) funksiyasini yozing. U muzlatilgan STANDART ga foydalanuvchi sozlamalarini qo'shib, yangi obyekt qaytarsin. Foydalanuvchi undefined bersa ham ishlasin. STANDART hech qachon o'zgarmasin. Ishora: Object.assign undefined manbani o'tkazib yuboradi.

Yechim
js
const STANDART = Object.freeze({
  til: "uz",
  valyuta: "so'm",
  chek: true,
});

function sozlamaYasa(foydalanuvchi) {
  return Object.assign({}, STANDART, foydalanuvchi);
}

console.log(sozlamaYasa({ chek: false }));
console.log(sozlamaYasa(undefined));
console.log(STANDART.chek); // true

Konsolda:

text
{ til: 'uz', valyuta: "so'm", chek: false }
{ til: 'uz', valyuta: "so'm", chek: true }
true

Birinchi argument — yangi {}, shuning uchun STANDART ga tegilmaydi (u muzlagan — tegilsa, modulda xato chiqardi). undefined manba jimgina o'tkazib yuborildi. Spread varianti ham ishlaydi: { ...STANDART, ...foydalanuvchi } — ...undefined obyekt ichida xatosiz e'tiborsiz qoladi.

3-mashq (qiyin): Ikki obyekt farqi

farqlar(eski, yangi) funksiyasini yozing: { qoshildi, olibTashlandi, ozgardi } qaytarsin — har biri kalitlar massivi. Qiymatlarni Object.is bilan solishtiring. Ishora: Object.keys ikkala obyektdan, Object.hasOwn — kalit bormi, filter — tanlash.

Yechim
js
function farqlar(eski, yangi) {
  const eskiKalitlar = Object.keys(eski);
  const yangiKalitlar = Object.keys(yangi);
  return {
    qoshildi: yangiKalitlar.filter((k) => !Object.hasOwn(eski, k)),
    olibTashlandi: eskiKalitlar.filter(
      (k) => !Object.hasOwn(yangi, k),
    ),
    ozgardi: eskiKalitlar.filter(
      (k) => Object.hasOwn(yangi, k) && !Object.is(eski[k], yangi[k]),
    ),
  };
}

const kecha = { osh: 35000, lagmon: 28000, somsa: 8000 };
const bugun = { osh: 38000, lagmon: 28000, manti: 30000 };

console.log(farqlar(kecha, bugun));

Konsolda:

text
{
  qoshildi: [ 'manti' ],
  olibTashlandi: [ 'somsa' ],
  ozgardi: [ 'osh' ]
}

(38 000 — misol uchun, kanonik narx 35 000.) ozgardi da ikki shart: kalit yangi obyektda ham bor va qiymati boshqa. Birinchi shartsiz o'chirilgan somsa ham "o'zgardi" ro'yxatiga tushardi (8000 va undefined farqli). Object.is — NaN qiymatlarni ham to'g'ri solishtirishi uchun. Bu funksiya sayoz: ichma-ich obyektlarni havola bo'yicha solishtiradi.

4-mashq: Vazifalar qadami — noma'lum filtrdan himoya

refactor/obyektlar branch'ida davom etamiz. filtrniTanla(filtr) filtr nomini tugmaning data-filtr atributidan oladi va hech tekshirmaydi:

js
function filtrniTanla(filtr) {
  holat.filtr = filtr;
  holat.tahrirId = null;
  render();
}

HTML'da imlo xatosi bo'lsa (data-filtr="faoll") yoki kimdir DevTools'da atributni o'zgartirsa, holat.filtr ga noma'lum nom tushadi. mosmi uni "hammasi" deb tushunadi, boshMatnlar[holat.filtr] esa undefined beradi.

Funksiya boshiga tekshiruv qo'shing: filtr nomi boshMatnlar ning o'z kaliti bo'lmasa — console.warn bilan ogohlantirib, hech narsa qilmasin. Mavjud uch tugmada xulq o'zgarmasin.

Yechim
js
function filtrniTanla(filtr) {
  if (!Object.hasOwn(boshMatnlar, filtr)) {
    console.warn(`Noma'lum filtr: ${filtr}`);
    return;
  }
  holat.filtr = filtr;
  holat.tahrirId = null;
  render();
}

boshMatnlar — uchta to'g'ri filtr nomining yagona ro'yxati: hammasi, faol, bajarilgan. Yangi ro'yxat yaratmadik — mavjud muzlatilgan obyektning kalitlaridan foydalandik.

Nega in emas, Object.hasOwn? Node'da solishtiring:

js
const boshMatnlar = Object.freeze({
  hammasi: "Hozircha vazifa yo'q. Birinchisini qo'shing!",
  faol: "Faol vazifa yo'q.",
  bajarilgan: "Bajarilgan vazifa hali yo'q.",
});

for (const nom of ["faol", "faoll", "toString"]) {
  const meros = nom in boshMatnlar;
  console.log(nom, meros, Object.hasOwn(boshMatnlar, nom));
}

Konsolda:

text
faol true true
faoll false false
toString true false

"toString" in boshMatnlar — true: in meros metodlarni ham ko'radi. Agar tekshiruv in bilan yozilsa, data-filtr="toString" li tugma tekshiruvdan o'tib ketardi. Brauzerda sinab ko'rdik: bunday tugma bosilganda holat.filtr "toString" bo'ladi, ro'yxat hamma vazifani ko'rsatadi, bo'sh ro'yxat xabari matniga esa function toString() { [native code] } yoziladi. Object.hasOwn bilan esa tugma hech narsa qilmaydi, konsolda faqat Noma'lum filtr: toString ogohlantirishi chiqadi.

Xulq o'zgarmaganini tekshiring: «Hammasi», «Faol», «Bajarilgan» — avvalgidek; "Bajarilgan" filtrida yangi vazifa qo'shilsa — filtr «Hammasi» ga o'tadi (bu yo'l ham filtrniTanla dan emas, vazifaQosh dan keladi, unga tegmadik).

Commit: Filtr: noma'lum filtr nomini Object.hasOwn bilan rad et.

9. Real ishda

  • Ma'lumotni qayta shakllantirish. Serverdan kelgan javobni ilovaga kerakli ko'rinishga aylantirish — entries/map/fromEntries ning kundalik ishi: kalitlarni qayta nomlash, keraksiz maydonlarni olib tashlash, qiymatlarni formatlash.
  • Sozlamalar. "Standart + foydalanuvchiniki" naqshi deyarli har kutubxonada bor: Object.assign({}, standart, opsiyalar) yoki spread. Options obyekti darsidagi g'oyaning davomi.
  • Xavfsizlik. Foydalanuvchi yuborgan kalitni tekshirish — faqat Object.hasOwn. Server kodida obj.hasOwnProperty ni sindiradigan kalitlar — ma'lum hujum usuli; yana bir xavfli hujumni Prototype pollution darsida ko'ramiz.
  • Kod ko'rib chiqishda. Object.assign(birorObyekt, ...) ni ko'rsangiz, birinchi savol: "bu obyektni o'zgartirish ataylabmi?". Ko'pincha javob "yo'q" bo'ladi va tuzatish bitta {} ga teng. Ikkinchi savol: for...in + hasOwnProperty yozilgan eski siklni Object.entries bilan qisqartirsa bo'lmaydimi?
  • React. Holat o'zgarishini Object.is bilan tekshiradi — shuning uchun holat obyektlarini joyida o'zgartirmay, yangisini yasaymiz.
  • Intervyu. "Object.assign va spread farqi?", "hasOwn nega hasOwnProperty dan yaxshi?", "obyektni qanday filtrlaysiz?" — o'rta darajali (middle) dasturchi intervyularida tez-tez uchraydi.

Xulosa

  • Object ning 23 statik metodi olti bo'limda: ko'rish, yasash/aylantirish, nusxalash, tekshirish, himoya, deskriptor/prototip.
  • Object.keys — sanaladigan o'z kalitlar; getOwnPropertyNames — sanalmaydiganlari bilan; getOwnPropertySymbols — symbol kalitlar.
  • Obyektni o'zgartirish naqshi: Object.fromEntries(Object.entries(o).map(...)) — juftlik kiradi, juftlik chiqadi.
  • Object.assign birinchi argumentni o'zgartiradi va uni qaytaradi; nishondagi setter'larni chaqiradi. Nusxa uchun — {} yoki spread.
  • Har doim Object.hasOwn: hasOwnProperty null-prototipli obyektda yo'q va ma'lumot bilan to'silishi mumkin.

Keyingi dars: Ichma-ich ma'lumotni immutable yangilash — chuqur joylashgan qiymatni asl obyektga tegmasdan yangilaymiz va vazifalar ni muzlagan ma'lumot bilan ishlaydigan qilamiz.

Manbalar

  • MDN: "Object" — "Static methods" bo'limi; "Object.assign()", "Object.fromEntries()", "Object.hasOwn()" — developer.mozilla.org
  • ECMAScript 2025 Language Specification: "Properties of the Object Constructor" — tc39.es/ecma262
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
JavaScript Object metodlari: assign, entries, fromEntries, hasOwn, is va boshqalar — to'liq sharh — IlmHamroh