այսպիսով javascript engine ը ունի առաջին հայացքից մի փոքր տարօրինակ բայց հետաքրքիր վարքագիծ այն փոփոխակաները class-ները function-ները բարձրացնում է տվիալ scop-ի ամենավերևը դա տեղի է ունենում compilation ի փուլում և կոչվում է hoisting այն օգտակար է բայց եթե չգիտես ինչպես է աշխատում կարող խնդիրներ առաջացնել
Function Hoisting
function printHello() {
console.log("hello")
}
printHello()
// hello
Այստեղ մենք հայտարարում ենք printHello ֆունկցիան և անմիջապես հետո կանչում այդ ֆունկցիան: Սխալներ չկան ամեն ինչ աշխատում է!
Այժմ նայեք այս օրինակին.
printHello()
// hello
function printHello() {
console.log("hello")
}
հմմ Այստեղ մենք կանչում ենք printHello ֆունկցիան նախքան այն հայտարարելը: Եվ ամեն ինչ դեռ աշխատում է առանց սխալների: Ի՞նչ է տեղի ունեցել այստեղ։ hoisting .
Նախքան interpreter-ը կկատարի կոդը, այն նախ բարձրացնում է հայտարարված ֆունկցիաները scop-ի ամենավերևը(այն scop-ի որում ֆունկցիան հայտարարված է)։ hoistion-ի միջոցով ֆունկցիան հասանելի է դառնում նույնիսկ նախքան հայտարարելը։
Տեսնենք մեկ այլ օրինակ.
printHello()
// hello
printWorld()
// ReferenceError: printWorld is not defined
function printHello() {
console.log('hello')
function printWorld() {
console.log("world")
}
}
Ինչպես տեսնում եք այստեղ, մենք հայտարարում ենք printHello ֆունկցիան. որը տպում է 'hello' այնուհետև հայտարարում ենք մեկ այլ ֆունկցիա, որը կոչվում է printWorld, որը տպում է 'world' , երբ կանչվում է:
Նախքան printHello ֆուկցիան հայտարարելը, մենք փորձում ենք կանչել այն՝ printHello(). և Այն հասանելի է (ի շնորհիվ hoisting ի այն բարձրացել է global scop ի ամենավերևը), ուստի մենք «hello» ենք տեսնում console-ում:
Բայց հետո մենք կանչում ենք printWorld-ը, և ստանում ենք ReferenceError. printWorld-ը սահմանված չէ : Արդյո՞ք hoisting ը տեղի չի ունենում printWorld ի դեպքում:
hoisting ը աշխատում է, բայց այն "բարձրացնում է" միայն այն scop ի վերին մաս, որտեղ հայտարարվել է ֆունկցիան տվիալ դեպքում printHello ֆունկցիայի սքոփի վերևը: Հետևաբար, այն հասանելի կլինի միայն այդ ֆունկցիայում: Եկեք թարմացնենք մեր կոդը.
printHello()
// hello
function printHello() {
printWorld()
// world
console.log('hello')
function printWorld() {
console.log("world")
}
}
Այժմ մենք կանչում ենք printWorld ֆունկցիան printHello ֆունկցիայի վերևում, բայց նախքան printWorld ը հայտարարելը և այն աշխատում է Քանի որ hoisting ը ֆունկցիան բարձրացնում է local scop ի վերևը, և մենք կարող ենք մուտք գործել այն նախքան հայտարարելը
hoisting-ը այս ամենը հնարավոր է դարձնում function declaration-ների համար: Բայց, հարկ է նաև նշել, որ այն չի աշխատի function expression-ների դեպքում: դրա մասին կգրեմ մեկ այլ անգամ
Հիմա եկեք նայենք փոփոխականների hoisting ը:
Variable Hoisting
Դուք կարող եք փոփոխականներ հայտարարել JavaScript-ում var, let, և const keyword-ներով: Եվ այս փոփոխականները կենթարկվեն hoisting-ի, բայց այլ կերպ: Սկսենք var-ից.
var
Նայեք այս օրինակին.
console.log(name)
// undefined
var name = "Dav"
Այստեղ մենք հայտարարում ենք name անունով փոփոխական, որի արժեքը «dav» է: Բայց երբ մենք փորձում ենք մուտք գործել փոփոխական նախքան այն հայտարարելը ոչ մի սխալ չենք ստանում: hoisting է տեղի ունեցել. name փոփոխականը "բարձրացվել է" ուստի թարգմանիչը «գիտի», որ կա փոփոխական, որը կոչվում է name: Եթե թարգմանիչը չիմանար, դուք կստանաք անունը սահմանված չէ : Եկեք փորձենք.
console.log(name)
// ReferenceError: name is not defined
var myName = "Dav"
Մենք ունենք փոփոխական, որը կոչվում է, myName (ոչ թե name): և ստանում ենք «անունը սահմանված չէ» սխալ, երբ փորձում ենք
վերցնել name-ի արժեքը: Թարգմանիչը «չգիտի» այս փոփոխականի մասին։
Վերադառնալով վերը նշված մեր օրինակին.
console.log(name)
// undefined
var name = "Dav"
Թեև hoisting ը տեղի է ունեցել այստեղ, բայց nameո ի արժեքը որոշված չէ, երբ մենք մուտք ենք գործում այն նախքան հայտարարելը: եթե փոփոխականը հայտարարված է var ով հայտարարությունը բարձրացվում է, բայց իր default արժեքով` undefined: Փաստացի արժեքը փոխվում է, երբ հայտարարման տողը կատարվում է և այդ տողից հետո փոփոխականին մուտք գործելով՝ մենք ստանում ենք իրական արժեքը.
`
console.log(name)
// undefined
var name = "Dav"
console.log(name)
// Dav
`
Ենթադրենք, name ը հայտարարել ենք ֆունկցիայի մեջ.
`
print()
console.log(name)
// ReferenceError: name is not defined
function print() {
var name = "Dav"
}
`
Այստեղ մենք ստանում ենք ReferenceError. անունը սահմանված չէ : Հիշեք, որ փոփոխականները բարձրացվում են, բայց միայն այն scop ի վերին մաս որտեղ նրանք հայտարարվել են: Այս դեպքում, name-ը հայտարարված է print ֆունկցիայում, այնպես որ այն կբարձրացվի այդ local scop-ի վերև: Փորձենք մուտք գործել այն ֆունկցիայում.
`
print()
function print() {
console.log(name)
// undefined
var name = "dav"
}
`
Փորձելով մուտք գործել name ֆունկցիայում, թեև այն գտնվում է հայտարարման տողից վեր, մենք սխալ չենք ստանում: Դա պայմանավորված է նրանով որ name ը բարձրացված է(hoisting), բայց մի մոռացեք, որ իր default արժեքով` undefined:
let
Թեև let փոփոխականները նույնպես ենթարկվում են hoisting ի, նրանք ունեն այլ վարքագիծ: Տեսնենք մի օրինակ.
console.log(name)
// ReferenceError: Cannot access 'name' before initialization
let name = "Dav"
Այստեղ մենք ստանում ենք ReferenceError. Հնարավոր չէ մուտք գործել «name» նախքան հայտարարելը : Նկատո՞ւմ եք, որ սխալն ասում է, որ name ը սահմանված չէ : Դա պայմանավորված է նրանով, որ թարգմանիչը «տեղյակ է» name փոփոխականի մասին, քանի որ փոփոխականը ենթարկվել է hoisting ի:
«Cannot access 'name' before initialization» տեղի է ունենում, քանի որ հայտարարված let փոփոխականները չունեն default արժեք, երբ ենթարկվում է hoisting-ի(բարձրացվում է): Ինչպես տեսանք var, փոփոխականներն ունեն default արժեք՝ undefined մինչդեռ let, փոփոխականները չեն 'սկզբնավորվում':
Փոփոխականները բարձրացվում են այն scop ի վերին մաս, որտեղ նրանք հայտարարված են (local կամ glbal), բայց հասանելի չեն, քանի որ չեն սկզբնավորվել: Այդ հատվածը կոչվում է Temporal Dead Zone(ժամանակավոր մեռյալ գոտի):
Դրանք կարող են հասանելի լինել միայն հայտարարման տողից հետո.
_const _
const ի դեպքում ամեն ինչ նույն է ինչ let ի դեպքում
console.log(name)
// ReferenceError: Cannot access 'name' before initialization
const name = "Dav"
Class
JavaScript-ի class-ները նույնպես բարձրացվում են(hoisting): Տեսնենք մի օրինակ.
const Dog = new Animal("jeko")
// ReferenceError: Cannot access 'Animal' before initialization
class Animal {
constructor(name) {
this.name = name
}
}
Այստեղ մենք հայտարարում ենք class, որը կոչվում է Animal. Մենք փորձում ենք մուտք գործել այս class (ստեղծելով Dog օբյեկտ) նախքան այն հայտարարելը: Մենք ստանում . ReferenceError հնարավոր չէ մուտք գործել «Animal» նախքան սկզբնավորումը : Ի՞նչ է ձեզ հիշեցնում այս սխալը:
Ճիշտ այնպես, ինչպես let և constփոփոխականների դեպքում, class ները բարձրացվում են այն scop ի վերևում, որտեղ նրանք սահմանվել են, բայց անհասանելի են այնքան ժամանակ, քանի դեռ չեն սկզբնավորվել:
Եկեք թարմացնենք կոդը.
class Animal {
constructor(name) {
this.name = name
}
}
const Dog = new Animal("jeko")
console.log(Dog)
// { name: 'jeko' }
Animal ը հայտարարելուց հետո այն դառնում է հասանելի, այնպես որ մենք կարող ենք ստեղծել Dog առանց սխալների:
և այսպես երբեմն կտեսնեք այսպիսի կոդ
՝՝՝
function1()
function2()
function3()
// lines of code
// lines of code
function function1() {...}
function function2() {...}
function function3() {...}
՝՝՝
այստեղ ֆունկցաները իրենց տրամաբանությամբ հայտարարված են ներգևում բայց օգտագործվում կոդի մեջ ավելի վերև այն աշխատում է ի շնորհիվ hoisting ի իսկ փոփոխականների և class ների դեպքում ամեն ինչ այլ է
Top comments (0)