DEV Community

Cover image for JavaScript EP3: Scope (Chain)⛓️🚧
phatsss
phatsss

Posted on

JavaScript EP3: Scope (Chain)⛓️🚧

ມາຮອດ 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())
Enter fullscreen mode Exit fullscreen mode

ຈາກ 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

ໂດຍພື້ນຖານແລ້ວ 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 ມີຕໍ່ຕົວປ່ຽນ.
key/value

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

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.
local scope

ໃນ 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 ແບບນີ້ກໍ່ໄດ້ເຊັ່ນກັນ. ຖ້າຍັງງົງກໍ່ໄປເບິ່ງຕົວຢ່າງນຳກັນເລີຍ😵‍💫.
ໃນຕົວຢ່າງຈະອະທິບາຍໃນລັກສະນະຂອງຂະບວນການໄຫຼຂອງນ້ຳຕົກ(ໄຫຼຈາກເທິງລົງລຸ່ມ).
waterfall
ຫຼື ກໍລະນີທີ່ມີ function ຊ້ອນກັນອີກກໍ່ຈະມີໜ້າຕາ ແລະ ຊົງຜົມປະມານນີ້:
deeper waterfall


ເຮົາລອງມາສຶກສາເບິ່ງ code ຕົວຢ່າງນີ້ໄປນຳກັນ
example code
ມັນຄ້າຍຄືກັນກັບຕົວຢ່າງຕັ້ງແຕ່ທຳອິດແທບຈະທຸກຢ່າງ, ແຕ່ເຖິງຢ່າງໃດກໍຕາມມັນມີຈຸດແຕກຕ່າງໃຫຍ່ໆເລີຍກໍ່ຈະແມ່ນ: ເຮົາໄດ້ປະກາດຕົວປ່ຽນ city ຢູ່ໃນ getPersonInfo function ແລະ ບໍ່ຢູ່ໃນ global scope. ໃນທີ່ນີ້ເຮົາບໍ່ໄດ້ invoke getPersonInfo function, ດັ່ງນັ້ນ ມັນຈະບໍ່ມີການສ້າງ local context ເຊັ່ນກັນ. ເຮົາລອງ access ເຖິງ value ຂອງ name, age ແລະ city ໃນ global context ດັ່ງນີ້:
call local scope from global
ຜົນທີ່ໄດ້ຄືມັນຈະທຳການໂຍນ 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
  }
} 
Enter fullscreen mode Exit fullscreen mode

ຖ້າເຮົາລອງ visualize scope ອອກມາກໍ່ຈະໄດ້:
block scope
ເຮົາມີ global scope, function scope ແລະ block scopes 2 ອັນ. ເຊິ່ງເຮົາສາມາດປະກາດຕົວປ່ຽນ message ໄດ້ 2 ຄັ້ງ, ເນື່ອງຈາກຕົວປ່ຽນຖືກກຳນົດ scope ໄວ້ໃນຂອບເຂດຂອງ brackets.


ສະຫຼຸບ:

  • ເຮົາຈະເຫັນວ່າ scope chain ເປັນ chain ຂອງການອ້າງອີງເຖິງ value ທີ່ເຮົາສາມາດ access ໄດ້ໃນ context ທີ່ເຮົາກຳລັງເຮັດຢູ່.
  • scope ເຮັດໃຫ້ເຮົາສາມາດ re-use ຊື່ຂອງຕົວປ່ຽນທີ່ໄດ້ຖືກປະກາດໄວ້ຢູ່ໃນ scope chain, ເນື່ອງຈາກມັນສາມາດເຮັດວຽກແບບລົງຊັ້ນລຸ່ມໄດ້ຢ່າງດດຽວ ແລະ ບໍ່ສາມາດຂຶ້ນໄປຊັ້ນເທິງຂອງ scope ໄດ້.

ອ້າງອີງ:
⚡️⛓JavaScript Visualized: Scope (Chain)

Top comments (0)