ມາຮອດ ep ນີ້, ເຊື່ອວ່າຫຼາຍໆຄົນກໍ່ອາດຈະເຄີຍຂຽນ JS ບໍ່ຫຼາຍກໍ່ໜ້ອຍ, ແຕ່ຈະພະຍາຍາມຍົກຕົວຢ່າງທີ່ງ່າຍ ແລະ ເຂົ້າໃຈໄດ້ພາຍໃນ 3 ວິນາທີ
ເຮົາມາເບິ່ງ code ກັນກ່ອນເລີຍ:
const name = "Lydia"
const age = 21
const city = "San Francisco"
function getPersonInfo() {
const name = "Sarah"
const age = 22
return `${name} is ${age} and lives in ${city}`
}
console.log(getPersonInfo())
ຈາກ code ຈະເຫັນວ່າເຮົາໄດ້ເຮັດການ invoke getPersonInfo
function ທີ່ມີການ return ຄ່າເປັນ string ອອກມາ, ໃນນັ້ນປະກອບດ້ວຍຕົວປ່ຽນ name
, age
ແລະ city
. ຜົນທີ່ໄດ້ຈາກ code ດ້ານເທິງແມ່ນ Sarah is 22 and lives in San Francisco
, ແຕ່ໃນ getPersonInfo
function ບໍ່ໄດ້ບັນຈຸຕົວປ່ຽນ city
ແລ້ວມັນຮູ້ຈັກຕົວປ່ຽນ city
ໄດ້ແນວໃດ?🤔.
ທຳອິດຈະມີການຈັດການພື້ນທີ່ memory ໃນຫຼາຍໆ context ທີ່ແຕກຕ່າງກັນ, ເຮົາມີ global context ເປັນ default(window
ໃນ browser ແລະ global
ໃນ Node) ແລະ local context ສຳລັບ getPersonInfo
function ທີ່ຖືກ invoke. ແຕ່ລະ context ກໍ່ຈະມີ scope chain ເຊັ່ນກັນ.
ສຳລັບ getPersonInfo
function, scope chain ຈະມີຂະບວນການປະມານນີ້:
ໂດຍພື້ນຖານແລ້ວ scope chain ເປັນ “chain of references” ໄປຫາ object ທີ່ມີການອ້າງອີງເຖິງ values(ແລະ scopes ອື່ນໆ)ທີ່ຖືກອ້າງອີງຢູ່ໃນ execution context. scope chain ຖືກສ້າງຂຶ້ນຕອນທີ່ execution context ຖືກສ້າງຂຶ້ນ, ໝາຍຄວາມວ່າມັນຖືກສ້າງຕອນ runtime.
ເຖິງຢ່າງໃດກໍ່ຕາມ, ເຮົາຈະຍັງບໍ່ເວົ້າເຖິງ activation object ຫຼື execution contexts ໃນບົດຄວາມນີ້ເທື່ອ(ໃນບົດຄວາມນີ້ເຮົາມາໂຟກັສທີ່ scope ກັນກ່ອນ). ດັ່ງຕົວຢ່າງດ້ານລຸ່ມ key/value ທີ່ຢູ່ນຳ execution contexts ຈະສະແດງເຖິງການອ້າງອີງທີ່ scope chain ມີຕໍ່ຕົວປ່ຽນ.
scope chain ຂອງ global execution context ມີການອ້າງອີງເຖິງ 3 ຕົວປ່ຽນຄື: name
ໂດຍມີຄ່າ Lydia
, age
ມີຄ່າ 21
ແລະ city
ມີຄ່າ San Francisco
. ໃນ local context ເຮົາມີການອ້າງອີງເຖິງ 2 ຕົວປ່ຽນຄື: name
ມີຄ່າ Sarah
ແລະ age
ມີຄ່າ 22
.
ເມື່ອເຮົາ access ເຂົ້າເຖິງຕົວປ່ຽນທີ່ຢູ່ໃນ getPersonInfo
, JS Engine ຈະທຳການກວດຢູ່ local scope chain ກ່ອນ.
local scope chain ມີການອ້າງອີງເຖິງ name
ແລະ age
, name
ມີຄ່າ Sarah
ແລະ age
ມີຄ່າ 22
. ເຮົາມາລອງສັງເກດເບິ່ງວ່າຖ້າເຮົາ access ຕົວປ່ຽນ city
ຈະເປັນຈັ່ງໃດ?
ເພື່ອຫາ value ຂອງຕົວປ່ຽນ city
, JS Engine ຈະທຳການລົງໄປຄົ້ນຫາຕາມ scope chain ໝາຍຄວາມວ່າຖ້າມັນບໍ່ພົບ value ໃນ local scope chain ມັນກໍ່ຈະທຳການຫາຢູ່ໃນ outer scope(scope ທີ່ນອກ local scope)ທີ່ local scope ໄດ້ມີການອ້າງອີງເຖິງ ໃນຕົວຢ່າງດ້ານລຸ່ມຈະແມ່ນ global object.
ໃນ global context ເຮົາໄດ້ປະກາດຕົວປ່ຽນ city
ມີຄ່າ San Francisco
, ດັ່ງນັ້ນ ຈຶ່ງມີການອ້າງອີງເຖິງຕົວປ່ຽນ city
. ຕອນນີ້ເຮົາມີ value ຂອງແຕ່ລະຕົວປ່ຽນແລ້ວຈຶ່ງເຮັດໃຫ້ getPersonInfo
function ສາມາດ return ຄ່າທີ່ເປັນ string ອອກມາໄດ້ ແລະ ຜົນທີ່ໄດ້ແມ່ນ Sarah is 22 and lives in San Francisco
.
ເຮົາສາມາດລົງໄປຊັ້ນລຸ່ມຂອງ scope chain ໄດ້, ແຕ່ບໍ່ສາມາດຂຶ້ນມາຊັ້ນເທິງຂອງ scope chain ໄດ້ ຫຼື ຈະເອີ້ນວ່າອອກນອກ scope ໄດ້ແຕ່ບໍ່ສາມາດເຂົ້າໄປໃນ scope ແບບນີ້ກໍ່ໄດ້ເຊັ່ນກັນ. ຖ້າຍັງງົງກໍ່ໄປເບິ່ງຕົວຢ່າງນຳກັນເລີຍ😵💫.
ໃນຕົວຢ່າງຈະອະທິບາຍໃນລັກສະນະຂອງຂະບວນການໄຫຼຂອງນ້ຳຕົກ(ໄຫຼຈາກເທິງລົງລຸ່ມ).
ຫຼື ກໍລະນີທີ່ມີ function ຊ້ອນກັນອີກກໍ່ຈະມີໜ້າຕາ ແລະ ຊົງຜົມປະມານນີ້:
ເຮົາລອງມາສຶກສາເບິ່ງ code ຕົວຢ່າງນີ້ໄປນຳກັນ
ມັນຄ້າຍຄືກັນກັບຕົວຢ່າງຕັ້ງແຕ່ທຳອິດແທບຈະທຸກຢ່າງ, ແຕ່ເຖິງຢ່າງໃດກໍຕາມມັນມີຈຸດແຕກຕ່າງໃຫຍ່ໆເລີຍກໍ່ຈະແມ່ນ: ເຮົາໄດ້ປະກາດຕົວປ່ຽນ city
ຢູ່ໃນ getPersonInfo
function ແລະ ບໍ່ຢູ່ໃນ global scope. ໃນທີ່ນີ້ເຮົາບໍ່ໄດ້ invoke getPersonInfo
function, ດັ່ງນັ້ນ ມັນຈະບໍ່ມີການສ້າງ local context ເຊັ່ນກັນ. ເຮົາລອງ access ເຖິງ value ຂອງ name
, age
ແລະ city
ໃນ global context ດັ່ງນີ້:
ຜົນທີ່ໄດ້ຄືມັນຈະທຳການໂຍນ ReferenceError
ສູດດັ້ງເດີມເຈົ້າເກົ່າມາໃສ່ໜ້າເຮົາ, ສາເຫດກໍ່ຍ້ອນມັນບໍ່ເຫັນຕົວປ່ຽນ city
ໃນ global scope, ອີກຢ່າງກໍ່ຄືເຮົາເອີນຈາກ global scope ຢູ່ແລ້ວມັນເລີຍບໍ່ມີ scope ຊັ້ນລຸ່ມໃຫ້ຫາອີກ ແລະ ມັນບໍ່ສາມາດຂຶ້ນໄປຊັ້ນເທິງຂອງ scope ໄດ້ນັ້ນເອງ.
ດ້ວຍວິທີນີ້ເຮົາສາມາດ protect ຕົວປ່ຽນຂອງເຮົາ ແລະ ສາມາດ re-use ຊື່ຕົວປ່ຽນຄືນໄດ້ອີກ.
ນອກຈາກ global scope ແລະ local scope ແລ້ວມັນຍັງມີ block scope ອີກ🤯. ຕົວປ່ຽນທີ່ປະກາດດ້ວຍ let
ແລະ const
keyword ຈະເປັນຕົວປ່ຽນທີ່ມີ scope ຢູ່ໃນ brackets ({}
).
const age = 21
function checkAge() {
if (age < 21) {
const message = "You cannot drink!"
return message
} else {
const message = "You can drink!"
return message
}
}
ຖ້າເຮົາລອງ visualize scope ອອກມາກໍ່ຈະໄດ້:
ເຮົາມີ global scope, function scope ແລະ block scopes 2 ອັນ. ເຊິ່ງເຮົາສາມາດປະກາດຕົວປ່ຽນ message
ໄດ້ 2 ຄັ້ງ, ເນື່ອງຈາກຕົວປ່ຽນຖືກກຳນົດ scope ໄວ້ໃນຂອບເຂດຂອງ brackets.
ສະຫຼຸບ:
- ເຮົາຈະເຫັນວ່າ scope chain ເປັນ chain ຂອງການອ້າງອີງເຖິງ value ທີ່ເຮົາສາມາດ access ໄດ້ໃນ context ທີ່ເຮົາກຳລັງເຮັດຢູ່.
- scope ເຮັດໃຫ້ເຮົາສາມາດ re-use ຊື່ຂອງຕົວປ່ຽນທີ່ໄດ້ຖືກປະກາດໄວ້ຢູ່ໃນ scope chain, ເນື່ອງຈາກມັນສາມາດເຮັດວຽກແບບລົງຊັ້ນລຸ່ມໄດ້ຢ່າງດດຽວ ແລະ ບໍ່ສາມາດຂຶ້ນໄປຊັ້ນເທິງຂອງ scope ໄດ້.