במאמר הזה נסביר על ההיקף ועל אופן הפעולה שלו ב-JavaScript.
היקף הוא מושג בסיסי ב-JavaScript ובשפות תכנות אחרות, שמגדיר את ההקשר שבו מתבצעת גישה למשתנים ומשתמשים בהם. ככל שתלמדו JavaScript ותעבוד יותר עם משתנים, הוא נעשה שימושי יותר לקוד שלכם.
ההיקף יכול לעזור לכם:
- שימוש בזיכרון באופן יעיל יותר: ההיקף מאפשר לטעון משתנים רק במקרה הצורך. אם המשתנה לא נמצא בהיקף, אין צורך להפוך אותו לזמין עבור הקוד שפועל כרגע.
- איתור ותיקון באגים בקלות רבה יותר: בידוד משתנים עם היקף מקומי מקל על פתרון באגים בקוד, מפני שבניגוד למשתנים גלובליים, ניתן לסמוך על כך שקוד מהיקף חיצוני לא יכול לטפל במשתנים עם היקף מקומי.
- יוצרים בלוקים קטנים של קוד לשימוש חוזר: לדוגמה, אפשר לכתוב פונקציה טהורה שלא מסתמכת על היקף חיצוני. אפשר להעביר פונקציה כזו בקלות למקום אחר עם שינויים קלים בלבד.
מהו היקף?
ההיקף של המשתנה קובע מאיפה בקוד אפשר להשתמש במשתנה.
JavaScript מגדיר משתנים בעלי היקף גלובלי או מקומי:
- משתנים עם היקף גלובלי זמינים מכל שאר ההיקפים בקוד JavaScript.
- משתנים עם היקף מקומי זמינים רק בהקשר מקומי ספציפי, והם נוצרים על ידי מילות מפתח, כמו
var
,let
ו-const
. אם אתם משתמשים במילות המפתחvar
,let
אוconst
כדי ליצור משתנה בתוך פונקציה, למשתנה הזה יש היקף מקומי.
חלקים מאוחרים יותר במאמר זה דנים בבלוק ובהיקף המילוני:
- משתני היקף זמינים באופן מקומי לבלוק, כפי שנקבע לפי המיקום של הסוגריים המסולסלים שבהם מוגדרת הצהרת החסימה. רק משתנים שהוצהרו עם מילות המפתח
let
אוconst
יש היקף חסימה. - היקף קלאסי משתמש במיקום שבו הוצהר על משתנה בקוד המקור כדי לקבוע איפה המשתנה זמין. משתמשים בסגירות כדי לתת לפונקציה סגורה גישה למשתנים שההיקף החיצוני ידוע כסביבה המילונית.
כשניגשים למשתנה במסגרת ההיקף שלו, JavaScript מחזיר את הערך שהוקצה לו או יוצר שגיאה באופן אחר.
כדי להצהיר על משתנה:
- צריך להשתמש במילות המפתח
var
,const
אוlet
כדי להצהיר על משתנים מקומיים או גלובליים. - צריך להשתמש במילות המפתח
const
אוlet
כדי להצהיר על משתני היקף ברמת הבלוק.
כשמצהירים על משתנה var
בפונקציה, ההצהרה הופכת אותו לזמין לפונקציה המקיפה הקרובה ביותר. אי אפשר להשתמש במילת המפתח var
כדי להצהיר על משתנים עם היקף חסימה.
דוגמאות להיקף
בדוגמה הזו מוצגת היקף גלובלי כי המשתנה greeting
מוצהר מחוץ לכל פונקציה או בלוק, ולכן הערך שלו זמין לכל הקוד במסמך הנוכחי:
const greeting = 'hello';
console.log(greeting); // 'hello'
בדוגמה של ההיקף הגלובלי, למשתנה greeting
מוקצה ערך hello
.
בדוגמה הזו מופיעה היקף מקומי כי היא מצהירה על המשתנה greeting
עם מילת המפתח let
בתוך פונקציה. המשתנה greeting
הוא משתנה ברמה מקומית, והוא לא זמין מחוץ לפונקציה.
function greet() {
let greeting = 'Hello World!';
console.log(greeting);
}
בדוגמה הזו מצוין היקף החסימה כי היא מצהירה על המשתנה greeting
בתוך בלוק כך שהמשתנה יהיה נגיש רק בתוך הסוגריים המסולסלים:
if (true) {
const greeting = 'hello';
}
console.log(greeting); // ReferenceError: greeting is not defined
חשוב לשים לב: כשהפונקציה console.log
מנסה להפיק את הערך של המשתנה greeting
, JavaScript מחזיר הודעת שגיאה ReferenceError
במקום הודעת hello
הצפויה. למה?
מוחזרת שגיאה כי למשתנה greeting
יש היקף ברמת הבלוק והבלוק הקרוב ביותר הוא חלק מההצהרה המותנית if
. אי אפשר לגשת למשתנים let
ו-const
שמצהירים עליהם בתוך בלוק שנמצא מחוץ לבלוק. כך אפשר לגשת למשתנה greeting
רק שבתוך הסוגריים המסולסלים, שמציין את היקף הבלוקים.
הדוגמה הזו מתקנת את השגיאה כי היא מעבירה את השיטה console.log(message)
בתוך הסוגריים המסולסלים. הקוד המעודכן מעביר את השיטה console.log(message)
לבלוק.
if (true) {
const greeting = 'hello';
console.log(greeting);
}
סוגי היקף
היקף גלובלי
ניתן לגשת למשתנים עם היקף גלובלי מכל מקום בתוכנית.
מומלץ להשתמש בקובץ HTML שמייבא שני קובצי JavaScript: file-1.js
ו-file-2.js
:
<script src="file-1.js"></script>
<script src="file-2.js"></script>
בדוגמה הזו, למשתנה globalMessage
יש היקף גלובלי והוא נכתב מחוץ לפונקציה. במהלך ההפעלה והביצוע, אפשר לגשת לערך של המשתנה globalMessage
מכל מקום בתוכנית JavaScript.
אפשר לראות את התוכן של הקבצים file-1.js
ו-file-2.js
בקטע הקוד הזה. שימו לב לזמינות של המשתנה globalMessage
בשני הקבצים.
// file-1.js
function hello() {
var localMessage = 'Hello!';
}
var globalMessage = 'Hey there!';
// file-2.js
console.log(localMessage); // localMessage is not defined
console.log(globalMessage); // Hey there!
יש סוג נוסף של היקף שלא נדון בו הרבה במאמר הזה. אם אתם יוצרים משתנה במודול של JavaScript אבל מחוץ לפונקציה או לבלוק, אין לו היקף גלובלי, אלא היקף מודול. משתנים עם היקף ברמת המודול זמינים בכל מקום במודול הנוכחי, אך אינם זמינים מקבצים או ממודולים אחרים. כדי שמשתנה ברמת המודול יהיה זמין לקבצים אחרים, צריך לייצא אותו מהמודול שבו הוא נוצר, ולאחר מכן import אותו מהמודול שצריך לגשת למשתנה.
היקף מקומי והיקף פונקציה
כשיוצרים משתנים בפונקציית JavaScript באמצעות מילות המפתח var
, let
או const
, המשתנים משתנים בהתאם לפונקציה, כך שאפשר לגשת אליהם רק מתוך הפונקציה. משתנים מקומיים נוצרים כשהפונקציה מתחילה, והם נמחקים בפועל בסיום הפעלת הפונקציה.
בדוגמה הזו מוצהר על המשתנה total
בפונקציה addNumbers()
. אפשר לגשת רק למשתנים a
, b,
ו-total
בתוך הפונקציה addNumbers()
.
function addNumbers(a, b) {
const total = a + b;
}
addNumbers(3, 4);
אפשר להשתמש במילות המפתח let
ו-const
כדי לתת שמות למשתנים. כשמשתמשים במילת המפתח let
, מערכת JavaScript יכולה לעדכן את המשתנה. עם זאת, עם מילת המפתח const
המשתנה נשאר קבוע.
var variable1 = 'Declared with var';
var variable1 = 'Redeclared with var';
variable1; // Redeclared with var
let variable2 = 'Declared with let. Cannot be redeclared.';
variable2 = 'let cannot be redeclared, but can be updated';
variable2; // let cannot be redeclared, but can be updated
const variable3 = 'Declared with const. Cannot be redeclared or updated';
variable3; // Declared with const. Cannot be redeclared or updated
חסימת ההיקף
חסימות משמשות לקיבוץ של הצהרה יחידה או קבוצה של דפי חשבון. אפשר להשתמש במילות המפתח const
או let
כדי להצהיר על משתנה מקומי ברמת בלוק. לתשומת ליבכם: אי אפשר להשתמש במילת המפתח var
כדי להצהיר על משתנים עם היקף חסימה.
לדוגמה, בבלוק הזה, ההיקף של המשתנה name
והערך שלו "Elizabeth"
נמצאים בתוך הסוגריים המסולסלים. משתנים בתוך טווח החסימה לא זמינים מחוץ לבלוק.
{
const name = "Elizabeth";
}
אפשר להשתמש במשתנים ברמת חסימה במשפטים if
, for
או while
.
יש לשים לב לשתי הלולאות של for
בקטע הקוד הזה. לולאת for
אחת משתמשת במילת המפתח var
כדי להצהיר על משתנה האתחול, שגדל במספרים 0
, 1
ו-2
. הלולאה השנייה מסוג for
משתמשת במילת המפתח let
כדי להצהיר על משתנה האתחול.
for (var i = 0; i < 2; i++) {
// ...
}
console.log(i); // 2
for (let j = 0; j < 2; j++) {
// ...
}
console.log(j); // The j variable isn't defined.
בדוגמת הקוד הקודמת, ייתכן שהבחנת שהמשתנה i
בלולאה הראשונה for
הודלף מחוץ ללולאה for
ועדיין שומר על הערך 2
, כי מילת המפתח var
לא משתמשת בהיקף בלוקים. הבעיה תוקנה בלולאת for
השנייה שבה המשתנה j
שהוצהר עם מילת המפתח let
מוקצה לבלוק של הלולאה for
ולא קיים אחרי שהלולאה for
מסתיימת.
שימוש חוזר בשם משתנה בהיקף אחר
ההיקף יכול לבודד משתנה בתוך פונקציה, גם אם משתמשים באותו שם משתנה במקום אחר בהיקף אחר.
בדוגמה הזו תוכלו לראות איך השימוש בהיקף מאפשר לכם לעשות שימוש חוזר באותו שם משתנה בפונקציות שונות:
function listOne() {
let listItems = 10;
console.log(listItems); // 10
}
function listTwo() {
let listItems = 20;
console.log(listItems); // 20
}
listOne();
listTwo();
למשתנים מסוג listItems
בפונקציות listOne()
ו-listTwo()
מוקצים הערכים הצפויים, כך שאין התנגשות ביניהם.
חסימות והיקף מילוני
סגירות הן פונקציה סגורה, שבה פונקציה פנימית יכולה לגשת להיקף הפונקציה החיצונית, שידועה גם כסביבה המילונית. כלומר, ב-JavaScript משתמשים בסגירות כדי לאפשר לפונקציות להפנות לסביבה המילונית החיצונית, שמאפשרת לקוד בתוך פונקציה להפנות למשתנים שהוצהרו מחוץ לפונקציה. למעשה, ניתן לתכנת שרשרת הפניות לסביבות מילוניות חיצוניות כך שפונקציה תקרא פונקציה, שבתורה נקראת פונקציה אחרת.
בדוגמה הזו, הקוד יוצר סגירה עם הסביבה המילונית שנוצרה כשמופעלת הפונקציה outer()
, והיא סוגרת מעל המשתנה hello
. לכן, המשתנה hello
נמצא בשימוש בתוך פונקציית הקריאה החוזרת setTimeout
.
function outer() {
const hello = 'world';
setTimeout(function () {
console.log('Within the closure!', hello)
}, 100);
}
outer();
בהיקף המילולי, ההיקף נקבע במהלך ההידור של קוד המקור, ולא בזמן הריצה. למידע נוסף על הסביבה המילונית, אפשר לעיין במאמר בנושא היקף וסגירה לאקסי.
מודולים
המודולים של JavaScript עוזרים לארגן את קוד JavaScript. כשמשתמשים בהם כראוי, הם מספקים מבנה יעיל ל-codebase ומסייעים בשימוש חוזר בקוד. במקום להשתמש במשתנים גלובליים כדי לשתף משתנים בין קבצים שונים, המודולים של JavaScript מספקים שיטה לייצוא וimport של משתנים.
// hello.js file
function hello() {
return 'Hello world!';
}
export { hello };
// app.js file
import { hello } from './hello.js';
console.log(hello()); // Hello world!
הדגמה של כלי ההמחשה של ההיקף
היקף הוא מושג בסיסי שכל מפתח JavaScript צריך להבין. כדי להבין טוב יותר את מערכת ההיקף, אפשר לנסות לכתוב קוד משלכם בעזרת JS Scope Visualizer. בהדגמה נעשה שימוש בצבעים בקוד כדי לעזור לך להציג באופן חזותי היקפים של JavaScript.
סיכום
במאמר הזה אנחנו מציגים סוגים שונים של היקפים. היקף JavaScript הוא אחד מהמושגים המתקדמים יותר בפיתוח אתרים, לכן טוב שקראת את התוכן הזה והקדישת זמן כדי להבין את הנושא.
ההיקף הוא לא תכונה שמוצגת למשתמשים. היא משפיעה רק על מפתח האתרים שכותב קוד, אבל אם יודעים איך פועל ההיקף, אפשר לתקן באגים כשהם נוצרים.