משתנים הם מבנה נתונים שמקצה שם מייצג לערך. הם יכולים להכיל נתונים מכל סוג.
שם המשתנה נקרא מזהה. צריך לציין מזהה חוקי אחרי כללים אלה:
- מזהים יכולים לכלול אותיות Unicode, סימני דולר ($), קו תחתון בתווים (_), ספרות (0-9) ואפילו תווי Unicode מסוימים.
- מזהים לא יכולים להכיל רווחים לבנים, כי המנתח משתמש ברווח לבן כדי
של רכיבי קלט נפרדים. לדוגמה, אם מנסים לקרוא למשתנה
my Variable
במקוםmyVariable
, המנתח רואה שני מזהים:my
ו-Variable
, וזורקת שגיאת תחביר ("אסימון לא צפוי: ". המזהים חייבים להתחיל באות, בקו תחתון (
_
) או בסימן דולר ($
). הם לא יכולים להתחיל בספרות, כדי למנוע בלבול בין מספרים מזהים:let 1a = true; > Uncaught SyntaxError: Invalid or unexpected token
אם JavaScript מאפשר שימוש במספרים בתחילת מזהה, הדבר יאפשר המזהים שמורכבים ממספרים בלבד, וגורמים להתנגשות בין מספרים שמשמשים מספרים ומספרים המשמשים כמזהים:
let 10 = 20 10 + 5 > ?
"מילים שמורות" אם יש להם משמעות תחבירית, אי אפשר להשתמש בהם כמזהים.
מזהים לא יכולים להכיל תווים מיוחדים (
! . , / \ + - * =
).
הכללים הבאים הם לא כללים מחמירים ליצירת מזהים, אבל שיעזרו לכם לשמור על הקוד בקלות רבה יותר. אם מודל לפרויקט יש סטנדרטים שונים, כדי לשמור על עקביות, צריך לפעול לפיהם.
בהתאם לדוגמה שהוגדרה על ידי השיטות והמאפיינים המובנים של JavaScript, תרחיש קאמל (מעוצב גם כ-camelCase) היא מוסכמה מקובלת מאוד שמורכב ממילים מרובות. מקרה של גמל היא שיטה שימוש באות רישית באות הראשונה של כל מילה מלבד הראשונה כדי לשפר את ללא רווחים.
let camelCasedIdentifier = true;
בפרויקטים מסוימים נעשה שימוש במוסכמות אחרות של מתן שמות בהתאם להקשר ולאופי של הנתונים. לדוגמה, האות הראשונה של כיתה בדרך כלל משתמשים באותיות רישיות, כך ששמות של מחלקות עם מספר מילים משתמשים בדרך כלל בגרסה של קאמל שנקרא בדרך כלל "קיסר קאמל עליון" או מקרה Pascal.
class MyClass {
}
המזהים צריכים לתאר בקצרה את אופי הנתונים שהם מכילים (ל
לדוגמה, currentMonthDays
הוא השם טוב יותר מאשר theNumberOfDaysInTheCurrentMonth
)
וקריאה בבירור במבט מהיר (originalValue
טוב יותר מ-val
).
myVariable
מזהים שנמצאים בשימוש במודול הזה פועלים בהקשר של
אבל בדוגמאות בודדות, זה לא יהיה שימושי מאוד בקוד הייצור, כי
לא מספקים שום מידע על הנתונים שהם מכילים.
המזהים לא צריכים להיות ספציפיים מדי לגבי הנתונים שהם מכילים, כי
הערכים שלהם יכולים להשתנות בהתאם לאופן שבו הסקריפטים פועלים על הנתונים האלה, או
ומקבלים החלטות שכל בעלי התוכן הדיגיטלי צריכים לקבל בעתיד. לדוגמה, משתנה שסופק במקור עם
יכול להיות שיהיה צורך לשנות את המזהה miles
לערך בקילומטרים מאוחר יותר
את הפרויקט, ולדרוש מהמנהלים לשנות את כל ההפניות למשתנה הזה
למנוע בלבול בעתיד. כדי למנוע זאת, צריך להשתמש ב-distance
בתור המזהה
במקום זאת.
JavaScript לא מעניק הרשאות מיוחדות או משמעות מיוחדת למזהים
מתחילים בתווים קו תחתון (_
), אבל בדרך כלל הם משמשים כדי להראות ש-
משתנה, שיטה או נכס הם "private", כלומר, המטרה היא רק
לשימוש בתוך ההקשר של האובייקט שמכיל אותו, והוא לא צריך להיות
בוצעה גישה או שונתה מחוץ להקשר הזה. זוהי מוסכמה שהועברה
משפות תכנות אחרות, ומקדם את ההוספה של JavaScript
נכסים פרטיים.
הצהרה לגבי משתנים
יש כמה דרכים להגביר את המודעות של JavaScript למזהה, לתהליך
שנקרא "הצהרה" משתנה. הוצהר על משתנה באמצעות הפרמטרים let
, const
,
או var
מילות מפתח.
let myVariable;
כדי להצהיר על משתנה שאפשר לשנות בכל שלב, צריך להשתמש ב-let
או ב-var
. האלה
מילות מפתח מציינות למפענח JavaScript שמחרוזת של תווים
שעשוי להכיל ערך.
כשעובדים ב-codebase מודרני, צריך להשתמש ב-let
במקום ב-var
. האפליקציה var
עדיין פועלת
בדפדפנים מודרניים, אבל יש בו כמה התנהגויות לא אינטואיטיביות
את הגרסאות המוקדמות ביותר של JavaScript, ולאחר מכן לא ניתן היה לשנות אותן מאוחר יותר
לשמור על תאימות לאחור. הקובץ let
נוסף ב-ES6 כדי לטפל בכמה בעיות
בעיצוב של var
.
משתנה מוצהר מאתחל על ידי הקצאת ערך למשתנה. צריך להשתמש ב
סימן שוויון יחיד (=
) כדי להקצות או להקצות מחדש ערך למשתנה. אפשר לבצע
כחלק מאותה הצהרה שמצהירה על כך:
let myVariable = 5;
myVariable + myVariable
> 10
אפשר גם להצהיר על משתנה עם let
(או var
) בלי לאתחל אותו
מיד. במקרה כזה, הערך הראשוני של המשתנה יהיה undefined
עד
מקצה לו ערך.
let myVariable;
myVariable;
> undefined
myVariable = 5;
myVariable + myVariable
> 10
משתנה עם ערך undefined
שונה ממשתנה לא מוגדר
המזהה עדיין לא הוצהר. הפניה למשתנה שלא
מוצהר וגורם לשגיאה.
myVariable
> Uncaught ReferenceError: myVariable is not defined
let myVariable;
myVariable
> undefined
שיוך של מזהה לערך נקרא בדרך כלל 'קישור'.
התחביר שמופיע אחרי מילות המפתח let
, var
או const
נקרא
"binding list", והוא מאפשר כמה הצהרות עם משתנים מופרדים בפסיקים
(שמסתיים בתו נקודה-פסיק הצפוי). הפעולה הזו יוצרת את קטעי הקוד הבאים
זהות מבחינה פונקציונלית:
let firstVariable,
secondVariable,
thirdVariable;
let firstVariable;
let secondVariable;
let thirdVariable;
להקצאה מחדש של ערך משתנה לא נעשה שימוש ב-let
(או ב-var
), מפני ש-JavaScript
כבר יודע שהמשתנה קיים:
let myVariable = true;
myVariable
> true
myVariable = false;
myVariable
> false
אפשר להקצות מחדש למשתנים ערכים חדשים על סמך הערכים הקיימים שלהם:
let myVariable = 10;
myVariable
> 10
myVariable = myVariable * myVariable;
myVariable
> 100
אם מנסים להצהיר מחדש על משתנה באמצעות let
בסביבת הייצור,
תקבלו שגיאת תחביר:
let myVariable = true;
let myVariable = false;
> Uncaught SyntaxError: redeclaration of let myVariable
דפדפנים כלים למפתחים
שמעניקות לך יותר הרשאות לגבי הצהרה מחדש של let
(ו-class
), כך שייתכן שלא
רואים את אותה שגיאה ב-Developer Console.
כדי לשמור על תאימות של דפדפנים מדור קודם, var
מאפשר הצהרה מחדש שאין בה צורך
ללא שגיאה באף הקשר:
var myVariable = true;
var myVariable = false;
myVariable\
> false
const
השתמשו במילת המפתח const
כדי להצהיר על קבוע, סוג של משתנה שחייב להיות
מאותחל באופן מיידי ואז לא ניתן לשינוי. מזהים של קבועים
פועלים לפי אותם הכללים כמו משתנים שהוצהרו באמצעות let
(ו-var
):
const myConstant = true;
myConstant
> true
אי אפשר להצהיר על קבוע בלי להקצות לו ערך באופן מיידי, כי
לא ניתן להקצות מחדש קבועים אחרי שהם נוצרים, כך שמודלים
יישאר undefined
לנצח. אם תנסו להצהיר על ערך קבוע
מבלי לאתחל אותו, תקבלו שגיאת תחביר:
const myConstant;
Uncaught SyntaxError: missing = in const declaration
לנסות לשנות את הערך של משתנה שהוצהר באמצעות const
, באופן שבו אפשר
שינוי הערך של משתנה מוצהר עם let
(או var
) גורם לסוג
שגיאה:
const myConstant = true;
myConstant = false;
> Uncaught TypeError: invalid assignment to const 'myConstant'
אבל כשקבוע משויך לאובייקט, המאפיינים של את האובייקט שניתן לשנות.
const constantObject = { "firstvalue" : true };
constantObject
> Object { firstvalue: true }
constantObject.secondvalue = false;
constantObject
> Object { firstvalue: true, secondvalue: false }
קבוע שמכיל אובייקט הוא בלתי ניתן לשינוי הפניה לערך נתונים שניתן לשינוי. לא ניתן לשנות את הקבוע עצמו, אבל המאפיינים של ההפניה אפשר לשנות, להוסיף או להסיר אובייקט:
const constantObject = { "firstvalue" : true };
constantObject = false
> Uncaught TypeError: invalid assignment to const 'constantObject'
אם אתם לא צופים שמשתנה מסוים יוקצה מחדש, מומלץ להקצות אותו מחדש.
קבוע. השימוש ב-const
מודיע לצוות הפיתוח או לתחזקם עתידיים על
אבל לא לשנות את הערך הזה, כדי למנוע פגיעה בהנחות שהקוד שלכם
לגבי אופן השימוש בו — לדוגמה, שבסופו של דבר משתנה
בהשוואה לסוג נתונים צפוי.
היקף המשתנים
היקף של משתנה הוא החלק בסקריפט שבו המשתנה זמין.
מחוץ להיקף של המשתנה, הוא לא יוגדר ולא כמזהה
שמכיל ערך של undefined
, אבל כאילו לא הוצהר עליו.
בהתאם למילת המפתח שבה משתמשים כדי להצהיר על משתנה ולהקשר איך מגדירים אותו, אפשר להגביל את ההיקף של המשתנים כדי לחסום הצהרות (היקף חסימה), פונקציות בודדות (היקף הפונקציה), או כל האפליקציה של JavaScript (היקף גלובלי).
חסימת היקף
כל משתנה שמצהירים עליו באמצעות let
או const
תוקצה להיקף הקרוב ביותר שלו
שמכיל הצהרת חסימה,
כלומר ניתן לגשת למשתנה רק בתוך אותו בלוק. מתבצע ניסיון
גישה למשתנה ברמת בלוק מחוץ לבלוק שמכיל אותו גורם
ומנסה לגשת למשתנה שאינו קיים:
{
let scopedVariable = true;
console.log( scopedVariable );
}
> true
scopedVariable
> ReferenceError: scopedVariable is not defined
מבחינת JavaScript, לא קיים משתנה עם היקף ברמת בלוק מחוץ לבלוק שבו הוא כלול. לדוגמה, אפשר להצהיר על ערך קבוע בתוך בלוק, ואז להצהיר על קבוע אחר מחוץ לאותו הבלוק שמשתמש אותו מזהה:
{
const myConstant = false;
}
const myConstant = true;
scopedConstant;
> true
משתנה שהוצהר לא יכול להרחיב את בלוק ההורה שלו, אבל הוא כן לכל בלוק הצאצאים:
{
let scopedVariable = true;
{
console.log( scopedVariable );
}
}
> true
אפשר לשנות את הערך של משתנה מוצהר מתוך בלוק צאצא:
{
let scopedVariable = false;
{
scopedVariable = true;
}
console.log( scopedVariable );
}
> true
אפשר לאתחל משתנה חדש עם let
או const
בתוך צאצא
חסימה ללא שגיאות, גם אם הוא משתמש באותו מזהה כמו משתנה
בלוק הורה:
{
let scopedVariable = false;
{
let scopedVariable = true;
}
console.log( scopedVariable );
}
> false
היקף הפונקציה
משתנים שהוצהרו באמצעות var
בהיקף של הפונקציה שמכילה את המשתנים הקרובים ביותר
(או בלוק אתחול סטטי בתוך מחלקה).
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
זה עדיין המצב אחרי קריאה לפונקציה. למרות המשתנה מאותחל בזמן שהפונקציה מתבצעת, והמשתנה עדיין לא זמין מחוץ להיקף הפונקציה:
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
myFunction();
> true
scopedVariable;
> ReferenceError: scopedVariable is not defined
היקף גלובלי
משתנה גלובלי זמין בכל אפליקציית JavaScript, בתוך כל הבלוקים והפונקציות, לכל סקריפט בדף.
אמנם זה יכול להיראות כמו ברירת מחדל רצויה, אבל משתנים שכל חלק לאפליקציה יכולה לגשת ולשנות אותה, ויכולה להוסיף תקורה מיותרת, או אפילו לגרום התנגשויות עם משתנים במקום אחר באפליקציה עם אותו מזהה. הכלל הזה חל על כל קוד JavaScript שמעורב בעיבוד של דף, כולל דברים כמו ספריות של צד שלישי וניתוח של נתוני משתמשים. לכן, שיטות מומלצות למניעת זיהום בהיקף הגלובלי ככל האפשר.
כל משתנה שהוצהר באמצעות var
מחוץ לפונקציית הורה, או באמצעות let
או
const
מחוץ לבלוק הורה, הוא גלובלי:
var functionGlobal = true; // Global
let blockGlobal = true; // Global
{
console.log( blockGlobal );
console.log( functionGlobal );
}
> true
> true
(function() {
console.log( blockGlobal );
console.log( functionGlobal );
}());
> true
> true
הקצאת ערך למשתנה בלי להצהיר עליו במפורש (כלומר
אף פעם לא משתמשים ב-var
, ב-let
או ב-const
כדי ליצור אותו) מעלה משתנה
היקף גלובלי, גם כשהוא מאותחל בתוך פונקציה או בלוק. משתנה
שנוצר באמצעות הדפוס הזה נקרא לפעמים "משתמע גלובלי".
function myFunction() {
globalVariable = "global";
return globalVariable
}
myFunction()\
> "global"
globalVariable\
> "global"
הרמה משתנה
הצהרות של משתנים ופונקציות מועברים לחלק העליון של ההיקף שלהם,
כלומר, רכיב התרגום של JavaScript מעבד כל משתנה שהוצהר בכל
בתסריט ומעביר אותו ביעילות לשורה הראשונה של
את ההיקף לפני הרצת הסקריפט. כלומר, משתנה שהוצהר באמצעות
אפשר להפנות אל var
לפני הצהרה על המשתנה בלי להיתקל ב-
שגיאה:
hoistedVariable
> undefined
var hoistedVariable;
כי רק הצהרת המשתנה מתארחת, לא האתחול,
משתנים שלא הוצהרו במפורש באמצעות var
, let
או const
שלא יועלו:
unhoistedVariable;
> Uncaught ReferenceError: unhoistedVariable is not defined
unhoistedVariable = true;
כפי שצוין קודם, משתנה מוצהר אבל לא מאומת
מוקצה לערך undefined
. ההתנהגות הזו חלה על משתנה שהוקדש
גם להצהרות, אלא רק להצהרות המשתמשים בהצהרה var
.
hoistedVariable
> undefined
var hoistedVariable = 2 + 2;
hoistedVariable\
> 4
ההתנהגות הלא אינטואיטיבית הזו היא בעיקר מחסום מהחלטות עיצוב שהתקבלו בגרסאות המוקדמות ביותר של JavaScript, ולא ניתן לשנות אותן ללא הסיכון לשבור אתרים קיימים.
let
ו-const
מטפלים בהתנהגות הזו על ידי הרצת שגיאה כאשר
מתבצעת גישה למשתנה לפני שהוא נוצר:
{
hoistedVariable;
let hoistedVariable;
}
> Uncaught ReferenceError: can't access lexical declaration 'hoistedVariable' before initialization
השגיאה הזו שונה מהשגיאה "hoistedVariable is לא מוגדר" שגיאה
כשתנסו לגשת למשתנה לא מוצהר. כי JavaScript
מעלה את המשתנה, הוא מודע לכך שהמשתנה ייווצר
את ההיקף הנתון. עם זאת, במקום להפוך את המשתנה לזמין לפני
עם הערך undefined
, המתרגם זורק שגיאה.
משתנים שהוצהרו עם let
או const
(או class
) נחשבים כקיימים
'אזור מתים זמני' ("TDZ") מתחילת החסימה שלו עד
של הנקודה בקוד שבה הוצהר על המשתנה.
לפי אזור המתים בזמן, ההתנהגות של let
לא אינטואיטיבית יותר מאשר ב-var
מחברים. הוא גם קריטי לעיצוב של const
. כי קבועים לא יכולים להיות
השתנה, קבוע כלפי מעלה מעל ההיקף שלו ונקבל ערך משתמע
לאחר מכן, לא ניתן היה לאתחל עם ערך משמעותי מתוך undefined
.
בדיקת ההבנה
עם אילו סוגי תווים אפשר להתחיל מזהה?
מהי השיטה המועדפת להצהרה על משתנה שהערך שלו ניתן לשנות בכל שלב?