המדריך האולטימטיבי ל-JavaScript

0 סקציות
חזרה לקורס JavaScript כל הקורסים

🚀 מבוא וחיבור לדף

JavaScript (בקיצור JS) היא שפת התכנות שמאפשרת להוסיף אינטראקטיביות, לוגיקה ודינמיות לדפי אינטרנט. בעוד HTML הוא השלד ו-CSS הוא העיצוב, JS הוא המוח.

איך מוסיפים JS לדף HTML?

1. קובץ חיצוני (השיטה המומלצת)

יוצרים קובץ נפרד (למשל script.js) ומקשרים אליו מה-HTML, רצוי לפני תג סגירת ה-</body>.

<body>
    <!-- ... כל תוכן ה-HTML ... -->
    
    <script src="script.js" defer></script>
</body>

המאפיין defer גורם לסקריפט להיטען במקביל ל-HTML ולהידחות הרצתו עד שה-HTML נטען במלואו, וזה מומלץ לביצועים.

2. קוד פנימי (Internal Script)

ניתן לכתוב JS ישירות בתוך תג <script>, גם כן רצוי בסוף ה-<body>.

<body>
    <!-- ... כל תוכן ה-HTML ... -->
    
    <script>
        console.log('שלום עולם!');
    </script>
</body>

הכירו את ה"קונסול החי"

ברוב הדוגמאות הבאות, החלון הימני אינו מציג דף אינטרנט, אלא מדמה את ה-**Console** של הדפדפן. כל פקודת console.log() שתכתבו בקוד תודפס שם, וכן שגיאות שיתרחשו.

📦 יסודות: משתנים וטיפוסים

בניגוד ל-Java, ג'אווהסקריפט היא שפת **טיפוסים דינמית** (Dynamically Typed). אין צורך להכריז על `int` או `String`. המנוע מבין את הטיפוס בזמן ריצה.

let, const, ו-var

  • const: הדרך המועדפת. מגדיר קבוע (constant) שלא ניתן להקצות מחדש (re-assign). זהו **Block Scoped**. (הערה: אם הקבוע הוא אובייקט או מערך, *ניתן* לשנות את תוכנם הפנימי).
  • let: להגדרת משתנה שערכו עשוי להשתנות. גם הוא **Block Scoped**.
  • var: הדרך הישנה. **Function Scoped**. מומלץ להימנע משימוש בה בקוד מודרני בגלל התנהגות מבלבלת עם Hoisting.

טיפוסים פרימיטיביים

טיפוס דוגמה הערה (מול Java)
Number 10, 3.14 אין הפרדה בין int, double, float. הכל Number.
String "שלום", 'עולם', `כאן ${name}` מחרוזת. ניתן להשתמש ב-` (Backticks) להטמעת משתנים.
Boolean true, false זהה ל-Java.
null null ערך "ריק" מכוון. (מעניין: typeof null מחזיר 'object', באג היסטורי).
undefined undefined טיפוס של משתנה שטרם הוקצה לו ערך. (ייחודי ל-JS)
Symbol Symbol('id') מזהה ייחודי ובלתי ניתן לשינוי (פחות נפוץ).
BigInt 100n למספרים שלמים גדולים מאוד (מסתיים ב-n).

קונסול חי: משתנים וטיפוסים

נסו לשנות את הערך של age ולראות את הפלט משתנה. נסו לשנות את name (שהוא const) ולראות את השגיאה בקונסול.

⚙️ אופרטורים

אופרטורים מאפשרים לבצע פעולות, השוואות והקצאות. רובם דומים ל-Java, אך יש כמה תוספות חשובות.

סוגי אופרטורים

סוג אופרטורים תיאור
חשבון +, -, *, /, % (מודולו), ** (חזקה) פעולות מתמטיות.
הקצאה =, +=, -=, *=, /= הקצאת ערכים למשתנים.
השוואה ==, !=, ===, !==, >, <, >=, <= השוואת ערכים. מומלץ תמיד להשתמש ב-=== (השוואה קפדנית) שבודק גם טיפוס וגם ערך, ולא ב-== (השוואה רפויה).
לוגיים && (וגם), || (או), ! (לא) צירוף תנאים בוליאניים.
טרנרי condition ? val1 : val2 קיצור של if...else.
Nullish Coalescing ?? מחזיר את הערך הימני *רק* אם הערך השמאלי הוא null או undefined. (שימושי לערכי 0 או false שצריך לשמר).
Optional Chaining ?. מאפשר לגשת למאפיינים מקוננים בבטחה. אם חוליה בשרשרת היא null או undefined, הביטוי מחזיר undefined במקום לזרוק שגיאה.

קונסול חי: אופרטורים מודרניים

🚦 בקרת זרימה

הלוגיקה הבסיסית של תנאים ולולאות. החלק הזה מאוד דומה ל-Java, עם תוספות כמו `for...of` ו-`for...in`.

קונסול חי: תנאים, Switch ולולאות

פונקציות

פונקציות הן אבני הבניין של הלוגיקה ב-JS. ניתן להגדיר אותן בכמה דרכים, והן יכולות לקבל פונקציות אחרות כארגומנטים (Higher-Order Functions).

קונסול חי: הגדרת פונקציות, פרמטרים ופונקציות מסדר גבוה

🔬 Scope & Closures

סקופ קובע את הנראות (visibility) של משתנים. Closure (סגור) הוא פונקציה ש"זוכרת" את הסביבה הלוקאלית שבה היא נוצרה, גם לאחר שהפונקציה החיצונית סיימה לרוץ.

סוגי סקופ

  • Global Scope: משתנה שמוגדר מחוץ לכל פונקציה. זמין בכל מקום.
  • Function Scope: משתנה שמוגדר עם `var` זמין *בכל* מקום בתוך הפונקציה שבה הוגדר.
  • Block Scope: משתנה שמוגדר עם `let` או `const` זמין *רק* בתוך הבלוק (`{...}`) שבו הוגדר (למשל, בתוך `if` או `for`).

קונסול חי: סקופ ו-Closure

מערכים ומתודות

מערכים ב-JS הם סופר-גמישים (בניגוד ל-Java). הם דינמיים ובעלי מתודות שימושיות רבות.

קונסול חי: מתודות מערכים

אלו המתודות הנפוצות ביותר לעבודה פונקציונלית עם מערכים.

אובייקטים ומתודות

אובייקטים ב-JS הם אוספים דינמיים של מפתח-ערך. הצורה הנפוצה היא Object Literal (סוגריים מסולסלים).

קונסול חי: אובייקטים, Destructuring ומתודות

מתודות מובנות (String, Number, Math)

לטיפוסים פרימיטיביים יש מתודות עזר שימושיות.

קונסול חי: מתודות שימושיות

מבני נתונים (Set, Map)

מבני נתונים מודרניים שנוספו ב-ES6 ופותרים בעיות נפוצות.

  • Set: אוסף של ערכים ייחודיים (Unique). מצוין להסרת כפילויות ממערך.
  • Map: אוסף של מפתח-ערך. בניגוד לאובייקט רגיל, המפתחות יכולים להיות *כל* טיפוס (כולל אובייקטים או פונקציות), לא רק מחרוזות.

קונסול חי: Set ו-Map

🏛️ Classes ו-Prototype (תכנות מונחה עצמים)

בניגוד ל-Java שהיא Class-Based, ג'אווהסקריפט היא Prototypal. אובייקטים יורשים ישירות מאובייקטים אחרים. התחביר של `class` (מ-ES6) הוא "סוכר תחבירי" (Syntactic Sugar) מעל מנגנון הפרוטוטייפ.

1. הדרך הישנה: פונקציית בנאי (Constructor Function) ו-Prototype

כך בנו אובייקטים לפני ES6. כל פונקציה יכולה לשמש כבנאי עם `new`. מתודות משותפות מוסיפים ל-`prototype` כדי לחסוך בזיכרון.

// 1. פונקציית הבנאי
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 2. הוספת מתודה ל-prototype המשותף
Person.prototype.greet = function() {
  console.log(`שלום, אני ${this.name} ואני בן ${this.age}.`);
};

const person1 = new Person("משה", 50);
person1.greet(); // "שלום, אני משה ואני בן 50."

2. הדרך המודרנית: `class` (ES6)

תחביר נקי ומוכר יותר (במיוחד למי שבא מ-Java), שעושה את אותו הדבר מאחורי הקלעים.

קונסול חי: `class`, `extends`, `super`

הקונספט 'this'

אחד הנושאים המבלבלים ב-JS. הערך של `this` נקבע *בזמן הריצה* (דינמית), בהתאם ל*איך הפונקציה נקראה*.

4 כללי `this`
  1. Default (Global): אם פונקציה נקראת רגיל (לא כמתודה, לא עם `new`, לא עם `bind`), `this` יצביע על האובייקט הגלובלי (window בדפדפן, או undefined ב-Strict Mode).
  2. Implicit (Method): אם פונקציה נקראת כמתודה של אובייקט (obj.myMethod()), `this` יצביע על האובייקט ש*משמאל לנקודה* (obj).
  3. New (Constructor): אם פונקציה נקראת עם `new` (new Person()), `this` יצביע על האובייקט החדש שנוצר.
  4. Explicit (Bind, Call, Apply): ניתן *לכפות* את הערך של `this` באמצעות .call(), .apply(), או .bind().

חריג: פונקציות חץ (Arrow Functions)
לפונקציות חץ *אין `this` משלהן*. הן יורשות את `this` באופן לקסיקלי מה-Scope שבו הן הוגדרו. הן מתעלמות מ-4 הכללים.

קונסול חי: הדגמת `this`

🌳 מניפולציית DOM ואירועים (Events)

ה-DOM (Document Object Model) הוא ה-API שמאפשר ל-JS לתקשר עם ה-HTML. אירועים (Events) הם הדרך להגיב לפעולות משתמש.

שיטות נפוצות

שיטה תיאור
document.getElementById(id) מוצא אלמנט לפי ה-ID הייחודי שלו.
document.querySelector(selector) מוצא את האלמנט *הראשון* שתואם לסלקטור CSS.
document.querySelectorAll(selector) מוצא את *כל* האלמנטים שתואמים לסלקטור CSS.
element.textContent קורא או משנה את הטקסט הפנימי (בטוח).
element.innerHTML קורא או משנה את ה-HTML הפנימי (פחות בטוח).
element.style.color = 'red' משנה מאפיין CSS.
element.classList.add('new') מוסיף קלאס CSS.
element.addEventListener(event, func) מאזין לאירוע (כמו 'click') ומפעיל פונקציה.
document.createElement('div') יוצר אלמנט חדש.
parent.append(child) מוסיף אלמנט ילד בסוף ההורה.

מעבדת DOM אינטראקטיבית

זוהי מעבדה מיוחדת. יש לכם עורך HTML ועורך JS. נסו לכתוב JS שמשנה את ה-HTML ולראות את התוצאה בחלון התצוגה המקדימה.

⚡ אסינכרוניות (Async)

הנושא החשוב ביותר ב-JS מודרני. JS פועלת ב-**Single Thread** עם **Event Loop**. היא לא "נתקעת" ומחכה לפעולות ארוכות (כמו קריאה לשרת), אלא ממשיכה הלאה ומטפלת בתשובה כשתגיע.

מכניקת ה-Event Loop
  1. Call Stack (מחסנית קריאות): קוד סינכרוני נכנס לכאן ומבוצע (LIFO - אחרון נכנס, ראשון יוצא).
  2. Web APIs (דפדפן): פעולות ארוכות (setTimeout, fetch, אירועי DOM) נשלחות לכאן. הדפדפן מטפל בהן "בצד".
  3. Callback Queue (תור): כשפעולת Web API מסתיימת, ה-Callback שלה נשלח לתור (FIFO).
  4. Event Loop: הלולאה שבודקת כל הזמן: "האם ה-Call Stack ריק?". אם כן, היא לוקחת את המשימה הראשונה מה-Callback Queue ודוחפת אותה ל-Call Stack כדי שתרוץ.

Microtask Queue: תור נוסף עם עדיפות גבוהה יותר (למשל, .then() של Promises). ה-Event Loop ירוקן *תמיד* את התור הזה לפני שהוא לוקח משהו מה-Callback Queue הרגיל.

קונסול חי: setTimeout, Promise, ו-fetch

שימו לב לסדר שבו ההודעות מופיעות בקונסול! "סוף" מופיע לפני שהתשובות האסינכרוניות חוזרות.

Async/Await (הדרך הנקייה ביותר)

תחביר מודרני (ES2017) שמאפשר לכתוב קוד אסינכרוני שנראה סינכרוני. זו פשוט "עטיפה" יפה סביב Promises.

קונסול חי: Async/Await

טיפול בשגיאות

קוד מקצועי חייב לדעת לטפל בשגיאות בחן, באמצעות try...catch...finally.

קונסול חי: try...catch

JSON (JavaScript Object Notation)

פורמט טקסטואלי סטנדרטי להעברת נתונים. קל מאוד ל-JS לקרוא ולכתוב אותו.

קונסול חי: JSON.stringify ו-JSON.parse

LocalStorage

מנגנון אחסון פשוט בדפדפן ששומר נתונים (כמחרוזות) באופן קבוע, גם לאחר סגירת הלשונית.

הערה: הדוגמה הזו תכתוב ל-LocalStorage האמיתי של הדפדפן שלכם. תוכלו לראות את התוצאות בלחיצה על F12 -> Application -> Local Storage.

קונסול חי: setItem, getItem

📦 מודולים (Modules)

הדרך המודרנית (ES6) לארגן קוד בקבצים נפרדים. קובץ אחד מייצא (export) פונקציות/משתנים, וקובץ אחר מייבא (import) אותם.

הערה: לא ניתן להדגים `import/export` בעורך החי הפשוט הזה, כיוון שהם דורשים מערכת קבצים אמיתית ושרת. זוהי דוגמה תיאורטית.

קובץ: math.js (ייצוא)
// ייצוא מוגדר (Named Export)
export const PI = 3.14;

export function add(a, b) {
  return a + b;
}

// ייצוא ברירת מחדל (Default Export)
export default function multiply(a, b) {
  return a * b;
}
קובץ: main.js (ייבוא)
// ייבוא ברירת מחדל וייבוא מוגדר
import multiply, { add, PI } from './math.js';

console.log(PI); // 3.14
console.log(add(2, 3)); // 5
console.log(multiply(2, 3)); // 6

// כדי שזה יעבוד ב-HTML:
// <script type="module" src="main.js"></script>

ביטויים רגולריים (Regex)

תחביר מיוחד לחיפוש והחלפת תבניות בתוך מחרוזות. כלי חזק מאוד (ולעיתים מורכב).

קונסול חי: test ו-match

🌐 Single Page Applications (SPA)

אפליקציית עמוד-יחיד (SPA) היא יישום ווב שטוען דף HTML יחיד וכל התוכן העתידי נטען באופן דינמי, ללא טעינה מחדש של הדף. זה יוצר חווית משתמש מהירה וזורמת, בדומה לאפליקציית דסקטופ.

איך זה עובד?

במקום לבקש דף HTML חדש מהשרת בכל ניווט, ה-SPA משתמש ב-JavaScript כדי לשנות את תוכן ה-DOM הנוכחי. בדרך כלל, השרת מספק רק את המידע (Data) בפורמט JSON, והלקוח (הדפדפן) אחראי על הרינדור (הצגת המידע).

יתרונות

  • מהירות: אחרי הטעינה הראשונית, המעברים בין "עמודים" הם כמעט מיידיים.
  • חווית משתמש: חוויה רציפה וזורמת ללא הבהובים של טעינת דפים.
  • הפחתת עומס על השרת: השרת שולח פחות מידע (רק נתונים, לא HTML מלא).

חסרונות

  • טעינה ראשונית איטית: צריך לטעון את כל ה-framework והקוד של האפליקציה בהתחלה.
  • אתגרי SEO: קשה יותר למנועי חיפוש לאנדקס תוכן שנטען דינמית (אם כי יש פתרונות).
  • תלות ב-JavaScript: אם JS מושבת בדפדפן, האתר לא יעבוד כלל.

פריימוורקים פופולריים

רוב ה-SPAs נבנים באמצעות ספריות ופריימוורקים מודרניים:

מעבדת DOM: דוגמת SPA בסיסית

זוהי דוגמה פשוטה המדגימה את העיקרון הבסיסי. שימו לב שלחיצה על הקישורים משנה את התוכן, אך הדפדפן לא מרענן את הדף.