Skip to content

Latest commit

 

History

History
96 lines (66 loc) · 9.81 KB

Iterating Over Object Properties with For-In.hy.md

File metadata and controls

96 lines (66 loc) · 9.81 KB

for in ցիկլի աշխատանքի առանձնահատկությունները: Ինչու՞ ցանկալի չէ այս ցիկլն օգտագործել զանգվածների իտերացիայի համար: Օբյեկտների մակերեսային պատճենումը for in ցիկլի օգնությամբ:

Ինչպես գիտենք for in ցիկլն օգտագործվում է օբյեկտների իտերացիայի համար։ Սակայն այստեղ գոյություն ունեն մի շարք նրբություններ, որոնք անհրաժեշտ է իմանալ՝ ցիկլը ճիշտ օգտագործելու համար։ Ցիկլն ունի հետևյալ ընդհանրական տեսքը՝

for (let key in object) {
  // Ցիկլի մարմինը
}

Ցիկլն աշխատում է հետևյալ կերպ՝

  • Սկզբից հայտարարվում է key փոփոխականը, որին հերթով վերագրվում է object անունով օբյեկտի բոլոր հատկությունների անունները (կամ ինչպես երբեմն ասում են՝ բանալիները)։ Փոփոխականին բնականաբար կարելի է տալ ցանկացած անուն, սակայն ինչպես ընդունված է սովորական for ցիկլի մեջ փոփոխականներն անվանել i, j կամ k, այնպես էլ for in ցիկլի մեջ փոփոխականին հիմնականում տրվում են key, prop կամ attribute անվանումները։

  • Ապա ցիկլը սկսում է արտածել օբյեկտի բոլոր թվարկելի հատկությունները։ Պետք է նշել, որ օբյեկտների մեջ կարող են լինել հատկություններ, որոնք թվարկելի չեն, և for in ցիկլը նրանց «չի նկատում»։ Դրանք այն հատկություններն են, որոնց ստեղծման ժամանակ enumerable ֆլագը նշված է որպես false: Նաև ինչպես գիտենք՝ սկսած ES6 ստանդարտից՝ օբյեկտների հատկությունների անունները կարող են լինել ոչ միայն String, այլ նաև Symbol տիպի։ for in ցիկլին հասանելի են միայն հատկությունների String տիպին պատկանող անունները, այն չի «տեսնում» հատկությունները, որոնց բանալին Symbol տիպի է։

  • Ցիկլի մարմնի մեջ գրված հրահանգը կատարվում է օբյեկտի յուրաքանչյուր հատկության համար։

  • Երբ օբյեկտի բոլոր թվարկելի հատկություններին արդեն հասանելիությունն ապահովված է, և ցիկլի մարմնում գրված հրահանգը յուրաքանչյուր հատկության համար կատարված՝ ցիկլն ընդհատում է աշխատանքը։

  • Ցիկլը հասանելիություն ունի նաև օբյեկտի պրոտոտիպերից ժառանգված բոլոր թվարկելի հատկություններին։

Ստեղծենք երկու օբյեկտ, որտեղ մեկը կհանդիսանա մյուսի պրոտոտիպը, և փորձենք այդ օբյեկտների հատկություններն արտածել for in ցիկլի օգնությամբ, որպեսզի ամեն ինչ ավելի պարզ լինի։

const fish = {
  canSwim: true,
};

const shark = {
  species: "great white",
  color: "white",
  __proto__: fish,
};

Այստեղ մենք ունենք fish և shark օբյեկտները, ընդորում shark օբյեկտի պրոտոտիպը հանդիսանում է fish օբյեկտը, հետևաբար shark օբյեկտը բացի իր «սեփական» հատկություններից, ունի նաև fish օբյեկտից ժառանգած հատկություններ։ Այժմ գրենք պարզ for in ցիկլ, որն ընդամենը պետք է alert անի shark օբյեկտի հատկությունների անունները՝

for (let key in shark) {
  alert(key);
}

Աշխատեցնելով կոդը, մենք կտեսնենք որ ցիկլն alert կանի հատկությունների species, color և canSwim անունները (բանալիները), որտեղից species և color հատկությունների անունները shark օբյեկտի «սեփականն» են, իսկ canSwim հատկության անունը նա ժառանգել է fish օբյեկտից, և for in ցիկլի համար նույնպես տեսանելի է։

Իսկ ի՞նչ անել, եթե մենք ցանկանում ենք գործ անել օբյեկտի միայն «սեփական» հատկությունների հետ։ Մենք կարող ենք ցիկլի մեջ լրացուցիչ ստուգում դնել hasOwnProperty մեթոդի օգնությամբ։ Վերևի օրինակի վրա այն կլինի հետևյալ ձևով՝

for (let key in shark) {
  if (shark.hasOwnProperty(key)) {
    alert(key);
  }
}

hasOwnProperty մեթոդի մասին առավել մանրամասն կարող եք նայել այս հղումով։

Այժմ եթե աշխատեցնենք կոդը, ապա կտեսնենք, որ alert է լինում shark օբյեկտի միայն «սեփական» հատկությունների անունները՝ species և color։

Արդեն գիտենք թե ինչպես for in ցիկլով ստանալ օբյեկտների հատկությունների անունները։ Այժմ տեսնենք թե ինչպես կարելի է ստանալ այդ հատկությունների արժեքները։

for (let key in shark) {
  alert(shark[key]);
}

Աշխատեցնելով այս կոդը կտեսնենք, որ alert-ը արտածում է shark օբյեկտի «սեփական» հատկությունների արժեքներ հանդիսացող "great white"-ը և "white"-ը, ինչպես նաև fish օբյեկտից ժառանգված true Բուլյան արժեքը։

Զանգվածների իտերացիայի համար for in ցիկլը նույնպես հնարավոր է օգտագործել, բայց խորհուրդ չի տրվում: Նախ for in ցիկլը չի երաշխավորում զանգվածի էլեմենտների ճիշտ հերթականությամբ արտածումը, ապա նաև այն օպտիմալացման ենթարկվում է միայն օբյեկտների հետ աշխատելու ժամանակ, զանգվածների պարագայում ինտերպրետատորի կողմից ոչ մի ներքին օպտիմալացում տեղի չի ունենում, և հետևաբար զանգվածների իտերացիան անհամեմատ դանդաղ է ընթանում։ Զանգվածների իտերացիայի համար միշտ ցանկալի է օգտագործել սովորական for ու ES6-ում ավելացված for of ցիկլերը, ինչպես նաև զանգվածների պրոտոտիպի forEach մեթոդը։

for in ցիկլը կարելի է նաև օգտագործել օբյեկտների մակերեսային պատճենման (shallow copy) նպատակով։ Այն իհարկե մակերեսային պատճենման լավագույն տարբերակը չէ, կան ավելի ճշգրիտ, կարճ տարբերակներ, բայց իմանալ պետք է ընդհանուր պատկերացման համար։

const shark = {
  species: "great white",
  color: "white",
};

const anotherShark = {};

for (let key in shark) {
  anotherShark[key] = shark[key];
}

console.log(shark === anotherShark); // false

Կոնսոլում՝ shark և նրա մակերեսային պատճենը հանդիսացող anotherShark օբյեկտների նույնականության ստուգումը վերադարձնում է false: Այսինքն նրանք իրարից արդեն բացարձակապես անկախ օբյեկտներն են։

JavaScript ծրագրավորման լեզվով ժամանակակից կոդ գրելիս հնարավորինս պետք է խուսափել ցիկլերի, այդ թվում նաև for in ցիկլի օգտագործումից։ Կարելի է օբյեկտների իտերացիայի համար օգտագործել Object.keys(obj), Object.values(obj) և Object.entries(obj) մեթոդները, որոնք թույլ կտան գրել լակոնիկ և դրա հետ մեկտեղ պարզ ու ընթեռնելի դեկլարատիվ կոդ։ Բացի դրանից այս մեթոդները վերադարձնում են օբյեկտի` համապատասխանաբար հատկությունների անունների, հատկությունների արժեքների և հատկություննների անուն-արժեք զույգի զանգվածները, որոնց վրա արդեն հեշտությամբ կարելի է կանչել զանգվածի մի քանի տասնյակի հասնող մեթոդներն ու կատարել այն բոլոր մանիպուլյացիաները, որոնք մեզ անհրաժեշտ կլինեն։ Վերը թվարկված մեթոդներին ավելի մանրամասն կարող եք ծանոթանալ այստեղ՝