מפתח
פרויקט לימוד שפת JavaScript בעברית, המיועד למתחילים עם דגש על סינטקס וצורת הכתיבה הנכונה.
מבנה הפרויקט
├── index.md # קובץ זה
├── guides/ # מדריכים תיאורטיים
│ ├── 01_background.md
│ ├── 02_syntax.md
│ ├── 03_variables.md
│ ├── 04_operators.md
│ ├── 05_conditionals.md
│ ├── 06_loops.md
│ ├── 07_functions.md
│ ├── 08_arrays.md
│ ├── 09_objects.md
│ ├── 10_dom.md
│ ├── 11_events.md
│ ├── 12_async.md
│ ├── 13_fetch_api.md
│ └── 14_best_practices.md
└── examples/ # קבצי קוד לדוגמא
├── 01_basics.js
├── 02_variables.js
├── 03_operators.js
├── 04_conditionals.js
├── 05_loops.js
├── 06_functions.js
├── 07_arrays.js
├── 08_objects.js
├── 09_dom_example.html
├── 10_events_example.html
├── 11_async.js
└── 12_fetch_example.html
איך להשתמש בפרויקט
הרצת קבצי JavaScript
# ב-Node.js
node examples/01_basics.js
# או בדפדפן דרך מסוף הפיתוח (DevTools Console)
צפייה בקבצי HTML
פתחו את קבצי ה-HTML בדפדפן כדי לראות את הדוגמאות בפעולה.
סדר לימוד מומלץ
- רקע והיסטוריה - הכרות עם השפה
- סינטקס בסיסי - כללי הכתיבה
- משתנים וטיפוסים - אחסון נתונים
- אופרטורים - פעולות חשבון והשוואה
- תנאים - קבלת החלטות בקוד
- לולאות - חזרה על פעולות
- פונקציות - ארגון קוד לשימוש חוזר
- מערכים - רשימות של נתונים
- אובייקטים - מבני נתונים מורכבים
- DOM - מניפולציה של דפי אינטרנט
- אירועים - תגובה לפעולות משתמש
- תכנות אסינכרוני - Promises ו-async/await
- קריאות שרת - עבודה עם APIs
- שיטות עבודה מומלצות - כתיבת קוד נקי
דרישות מקדימות
- הבנה בסיסית של HTML ו-CSS
- עורך קוד (מומלץ: VS Code)
- דפדפן מודרני (Chrome, Firefox, Edge)
- Node.js (להרצת קוד מחוץ לדפדפן)
רקע והיסטוריה של JavaScript
מה זה JavaScript?
JavaScript (בקיצור: JS) היא שפת תכנות דינמית המשמשת בעיקר לפיתוח אתרי אינטרנט אינטראקטיביים. היא אחת משלוש השפות הבסיסיות של פיתוח ווב:
| שפה | תפקיד |
|---|---|
| HTML | מבנה הדף (תוכן) |
| CSS | עיצוב הדף (מראה) |
| JavaScript | התנהגות הדף (אינטראקטיביות) |
היסטוריה קצרה
1995 - הלידה
- נוצרה ב-10 ימים בלבד על ידי Brendan Eich בחברת Netscape
- השם המקורי היה Mocha, לאחר מכן LiveScript, ולבסוף JavaScript
1997 - תקינה
- הפכה לתקן בינלאומי בשם ECMAScript
- מנוהלת על ידי ארגון ECMA International
2009 - Node.js
- יצירת Node.js אפשרה להריץ JavaScript מחוץ לדפדפן
- JavaScript הפכה לשפת Full-Stack
2015 - ES6/ES2015
- עדכון משמעותי שהוסיף תכונות מודרניות רבות
- מאז, גרסה חדשה יוצאת כל שנה
JavaScript לעומת Java
⚠️ חשוב להבין: JavaScript ו-Java הן שפות שונות לחלוטין!
| JavaScript | Java |
|---|---|
| שפה מפורשת (interpreted) | שפה מהודרת (compiled) |
| typyng דינמי | typing סטטי |
| מבוססת prototype | מבוססת class |
| בעיקר לווב | בעיקר לאפליקציות |
השם "JavaScript" נבחר משיקולי שיווק בלבד, בגלל הפופולריות של Java באותה תקופה.
איפה JavaScript רצה?
1. בדפדפן (Browser)
┌─────────────────────────────────┐
│ דפדפן (Chrome) │
│ ┌───────────────────────────┐ │
│ │ מנוע JavaScript │ │
│ │ (V8) │ │
│ └───────────────────────────┘ │
│ │
│ HTML ←→ CSS ←→ JavaScript │
└─────────────────────────────────┘
כל דפדפן מודרני כולל מנוע JavaScript: - Chrome: V8 - Firefox: SpiderMonkey - Safari: JavaScriptCore (Nitro) - Edge: V8 (בעבר Chakra)
2. בשרת (Node.js)
┌─────────────────────────────────┐
│ Node.js │
│ ┌───────────────────────────┐ │
│ │ מנוע JavaScript │ │
│ │ (V8) │ │
│ └───────────────────────────┘ │
│ │
│ גישה למערכת קבצים, רשת, וכו' │
└─────────────────────────────────┘
למה ללמוד JavaScript?
פופולריות
- השפה הפופולרית בעולם לפיתוח ווב
- קהילה עצומה ותיעוד רב
גמישות
- פיתוח Frontend (React, Vue, Angular)
- פיתוח Backend (Node.js, Express)
- אפליקציות מובייל (React Native)
- אפליקציות דסקטופ (Electron)
נגישות
- קל להתחיל - רק צריך דפדפן
- תוצאות מיידיות וויזואליות
- הרבה משאבי לימוד חינמיים
ביקוש בשוק העבודה
- דרישה גבוהה למפתחי JavaScript
- מגוון רחב של אפשרויות קריירה
כלים נדרשים
עורך קוד
מומלץ: Visual Studio Code (VS Code) - חינמי - תוספים רבים ל-JavaScript - IntelliSense (השלמה אוטומטית)
דפדפן
כל דפדפן מודרני עם כלי פיתוח (DevTools):
- F12 או Ctrl+Shift+I לפתיחה
- לשונית Console להרצת קוד
Node.js (אופציונלי)
להרצת JavaScript מחוץ לדפדפן:
- הורדה מ-nodejs.org
- בדיקת התקנה: node --version
הקובץ הראשון שלך
אפשרות 1: בתוך HTML
<!DOCTYPE html>
<html>
<head>
<title>הקוד הראשון שלי</title>
</head>
<body>
<h1>שלום עולם!</h1>
<script>
// הקוד שלך כאן
console.log("שלום עולם!");
alert("זה עובד!");
</script>
</body>
</html>
אפשרות 2: קובץ נפרד
<!-- index.html -->
<script src="script.js"></script>
// script.js
console.log("שלום מקובץ חיצוני!");
אפשרות 3: במסוף הדפדפן
- פתחו את DevTools (
F12) - עברו ללשונית Console
- הקלידו:
console.log("שלום!") - לחצו Enter
סיכום
- JavaScript היא שפת התכנות העיקרית לפיתוח ווב
- נוצרה ב-1995 והתפתחה מאז משמעותית
- רצה בדפדפנים ובשרתים (Node.js)
- קלה ללמידה עם תוצאות מיידיות
- דרושה מאוד בשוק העבודה
סינטקס בסיסי של JavaScript
מבנה בסיסי של קוד
JavaScript מורכבת מפקודות (statements) שמבוצעות בזו אחר זו מלמעלה למטה.
// פקודה ראשונה
console.log("שלום");
// פקודה שנייה
console.log("עולם");
נקודה-פסיק (Semicolon)
נקודה-פסיק ; מסמנת סוף פקודה:
// עם נקודה-פסיק (מומלץ)
let name = "דן";
console.log(name);
// בלי נקודה-פסיק (עובד, אבל פחות מומלץ)
let age = 25
console.log(age)
💡 המלצה: השתמשו תמיד בנקודה-פסיק לבהירות ומניעת באגים.
הערות (Comments)
הערות הן טקסט שהמחשב מתעלם ממנו - מיועדות לתיעוד והסברים.
הערה בשורה אחת
// זו הערה - המחשב מתעלם ממנה
let x = 5; // אפשר גם בסוף שורה
הערה מרובת שורות
/*
זו הערה ארוכה
שמשתרעת על
כמה שורות
*/
let y = 10;
מתי להשתמש בהערות?
// ✅ טוב - מסביר למה, לא מה
// מחשב מחיר עם הנחה של 10% ללקוחות ותיקים
let finalPrice = price * 0.9;
// ❌ לא טוב - מסביר את המובן מאליו
// מגדיר משתנה x שווה ל-5
let x = 5;
רגישות לאותיות (Case Sensitivity)
JavaScript מבדילה בין אותיות גדולות וקטנות:
// אלה שלושה משתנים שונים!
let name = "דן";
let Name = "דנה";
let NAME = "דני";
console.log(name); // "דן"
console.log(Name); // "דנה"
console.log(NAME); // "דני"
⚠️ שימו לב:
console.log≠Console.Log≠CONSOLE.LOG
רווחים והזחות (Whitespace & Indentation)
JavaScript מתעלמת מרווחים מיותרים, אבל הזחות חשובות לקריאות:
// ❌ קשה לקריאה
if(age>18){console.log("בגיר")}
// ✅ קריא ומסודר
if (age > 18) {
console.log("בגיר");
}
כללי הזחה
- השתמשו ב-2 או 4 רווחים (עדיף דרך Tab)
- כל בלוק קוד בתוך
{ }מוזח פנימה - היו עקביים לאורך כל הקוד
function greet(name) {
if (name) {
console.log("שלום " + name);
} else {
console.log("שלום אורח");
}
}
console.log - הדפסה למסוף
הפקודה הכי חשובה למתחילים! מדפיסה מידע למסוף (Console).
שימוש בסיסי
console.log("שלום עולם!"); // טקסט
console.log(42); // מספר
console.log(true); // ערך בוליאני
console.log(3.14); // מספר עשרוני
הדפסת מספר ערכים
console.log("שמי", "דן"); // שמי דן
console.log("הגיל שלי:", 25); // הגיל שלי: 25
console.log(1, 2, 3, 4, 5); // 1 2 3 4 5
הדפסת משתנים
let name = "דנה";
let age = 30;
console.log(name); // דנה
console.log("שם:", name, "גיל:", age); // שם: דנה גיל: 30
Template Literals (מומלץ!)
let name = "דן";
let age = 25;
// שימוש ב-backticks (`) ו-${}
console.log(`שמי ${name} ואני בן ${age}`);
// פלט: שמי דן ואני בן 25
סוגי console נוספים
console.log("מידע רגיל"); // הדפסה רגילה
console.warn("אזהרה!"); // אזהרה (צהוב)
console.error("שגיאה!"); // שגיאה (אדום)
console.info("מידע"); // מידע
console.table([1, 2, 3]); // הצגה כטבלה
בלוקים של קוד
בלוק קוד מוגדר על ידי סוגריים מסולסלים { }:
// בלוק של if
if (condition) {
// קוד בתוך הבלוק
console.log("התנאי התקיים");
}
// בלוק של פונקציה
function sayHello() {
// קוד בתוך הפונקציה
console.log("שלום!");
}
// בלוק של לולאה
for (let i = 0; i < 5; i++) {
// קוד שחוזר על עצמו
console.log(i);
}
מילים שמורות (Reserved Words)
מילים ש-JavaScript משתמשת בהן ואסור להשתמש בהן כשמות משתנים:
// ❌ שגיאה! אלה מילים שמורות
let if = 5;
let function = "שלום";
let return = true;
// ✅ תקין
let myIf = 5;
let myFunction = "שלום";
let returnValue = true;
רשימה חלקית של מילים שמורות
break, case, catch, continue, debugger, default, delete,
do, else, finally, for, function, if, in, instanceof,
new, return, switch, this, throw, try, typeof, var,
void, while, with, class, const, let, export, import,
extends, static, super, yield
סדר הביצוע
הקוד מתבצע מלמעלה למטה, שורה אחרי שורה:
console.log("1 - ראשון");
console.log("2 - שני");
console.log("3 - שלישי");
// פלט:
// 1 - ראשון
// 2 - שני
// 3 - שלישי
יוצאי דופן
- פונקציות - מוגדרות אבל לא רצות עד שקוראים להן
- קוד אסינכרוני - יכול לרוץ מאוחר יותר
console.log("1");
function hello() {
console.log("2 - בתוך הפונקציה");
}
console.log("3");
hello(); // קריאה לפונקציה
console.log("4");
// פלט:
// 1
// 3
// 2 - בתוך הפונקציה
// 4
איפה לכתוב JavaScript?
1. בתוך HTML (Inline)
<button onclick="alert('לחצת!')">לחץ עליי</button>
2. בתג script בתוך HTML
<script>
console.log("שלום!");
</script>
3. בקובץ חיצוני (מומלץ!)
<!-- index.html -->
<script src="app.js"></script>
// app.js
console.log("שלום מקובץ חיצוני!");
💡 המלצה: תמיד השתמשו בקובץ חיצוני לקוד JavaScript.
סיכום כללי הסינטקס
| כלל | דוגמה |
|---|---|
| סיום פקודה | let x = 5; |
| הערה בשורה | // הערה |
| הערה מרובה | /* הערה */ |
| רגישות לאותיות | name ≠ Name |
| הזחה | 2 או 4 רווחים |
| בלוק קוד | { ... } |
| הדפסה | console.log(...) |
משתנים וטיפוסי נתונים
מה זה משתנה?
משתנה הוא כמו קופסה עם שם שמאחסנת מידע. אפשר לשים בה ערך, לקרוא אותו, ולשנות אותו.
// יצירת משתנה בשם "age" עם הערך 25
let age = 25;
// קריאת הערך
console.log(age); // 25
// שינוי הערך
age = 26;
console.log(age); // 26
שלוש דרכים להכריז על משתנה
let - משתנה ניתן לשינוי
let name = "דן";
name = "דנה"; // ✅ מותר לשנות
console.log(name); // "דנה"
const - קבוע (לא ניתן לשינוי)
const PI = 3.14159;
PI = 3.14; // ❌ שגיאה! אי אפשר לשנות const
const API_URL = "https://api.example.com";
var - הדרך הישנה (לא מומלץ)
var oldWay = "לא מומלץ להשתמש";
// var יש לו בעיות עם scope, עדיף let
ההבדלים בין let, const ו-var
| תכונה | let | const | var |
|---|---|---|---|
| שינוי ערך | ✅ כן | ❌ לא | ✅ כן |
| Block scope | ✅ כן | ✅ כן | ❌ לא |
| Hoisting | ❌ לא זמין | ❌ לא זמין | ✅ זמין (undefined) |
| הכרזה מחדש | ❌ לא | ❌ לא | ✅ כן |
דוגמה ל-Block Scope
if (true) {
let x = 10;
var y = 20;
}
console.log(y); // 20 - var נגיש מחוץ לבלוק
console.log(x); // ❌ שגיאה! let לא נגיש מחוץ לבלוק
💡 כלל אצבע: השתמשו ב-
constכברירת מחדל. השתמשו ב-letרק כשצריך לשנות את הערך.
כללים לשמות משתנים
מה מותר?
let name = "דן"; // ✅ אותיות
let age2 = 25; // ✅ ספרות (לא בהתחלה)
let first_name = "דן"; // ✅ קו תחתון
let $price = 100; // ✅ סימן דולר
let _private = "סודי"; // ✅ קו תחתון בהתחלה
מה אסור?
let 2name = "דן"; // ❌ מתחיל בספרה
let my-name = "דן"; // ❌ מקף
let my name = "דן"; // ❌ רווח
let for = "דן"; // ❌ מילה שמורה
מוסכמות שמות (Naming Conventions)
// camelCase - הכי נפוץ ב-JavaScript
let firstName = "דן";
let totalAmount = 100;
let isLoggedIn = true;
// SCREAMING_SNAKE_CASE - לקבועים
const MAX_SIZE = 100;
const API_KEY = "abc123";
// PascalCase - לclass וcomponents
class UserProfile { }
function UserCard() { }
טיפוסי נתונים פרימיטיביים (Primitives)
JavaScript מכילה 7 טיפוסים פרימיטיביים:
1. String - מחרוזת
let name = "דן"; // גרשיים כפולות
let city = 'תל אביב'; // גרש בודד
let greeting = `שלום ${name}`; // template literal
console.log(greeting); // "שלום דן"
2. Number - מספר
let age = 25; // מספר שלם
let price = 19.99; // מספר עשרוני
let negative = -10; // מספר שלילי
let big = 1000000; // מספר גדול
let scientific = 2.5e6; // 2,500,000 (כתיב מדעי)
// ערכים מיוחדים
let infinity = Infinity;
let notANumber = NaN; // Not a Number
3. Boolean - ערך אמת/שקר
let isActive = true;
let isLoggedIn = false;
// תוצאות של השוואות
let isAdult = age >= 18; // true
let isEmpty = name === ""; // false
4. undefined - לא מוגדר
let x;
console.log(x); // undefined
// משתנה שהוכרז אבל לא קיבל ערך
let user;
console.log(user); // undefined
5. null - ריק במכוון
let user = null; // אין משתמש כרגע
// ההבדל מ-undefined:
// undefined = לא הוגדר
// null = הוגדר במכוון כריק
6. Symbol - ייחודי
let id1 = Symbol("id");
let id2 = Symbol("id");
console.log(id1 === id2); // false - כל Symbol ייחודי
7. BigInt - מספרים גדולים מאוד
let bigNumber = 9007199254740991n;
let anotherBig = BigInt("12345678901234567890");
typeof - בדיקת סוג
האופרטור typeof מחזיר את סוג המשתנה:
console.log(typeof "שלום"); // "string"
console.log(typeof 42); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (באג היסטורי!)
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"
המרות בין סוגים (Type Conversion)
המרה למחרוזת
let num = 42;
let str = String(num); // "42"
let str2 = num.toString(); // "42"
let str3 = num + ""; // "42" (טריק)
המרה למספר
let str = "42";
let num = Number(str); // 42
let num2 = parseInt(str); // 42 (שלם)
let num3 = parseFloat("3.14"); // 3.14 (עשרוני)
let num4 = +str; // 42 (טריק)
// מקרים מיוחדים
Number("abc"); // NaN
Number(""); // 0
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(undefined); // NaN
המרה לבוליאני
Boolean(1); // true
Boolean(0); // false
Boolean("שלום"); // true
Boolean(""); // false
Boolean(null); // false
Boolean(undefined); // false
// ערכים שהם false (falsy):
// 0, "", null, undefined, NaN, false
// כל השאר הם true (truthy)
חיבור מחרוזות (String Concatenation)
let first = "שלום";
let last = "עולם";
// שיטה 1: אופרטור +
let full = first + " " + last; // "שלום עולם"
// שיטה 2: Template Literals (מומלץ!)
let message = `${first} ${last}!`; // "שלום עולם!"
// שימוש מתקדם ב-template literals
let name = "דן";
let age = 25;
let intro = `שמי ${name}.
אני בן ${age}.
בעוד 5 שנים אהיה בן ${age + 5}.`;
עבודה עם מחרוזות
let text = "שלום עולם";
// אורך
console.log(text.length); // 9
// גישה לתו (0-indexed)
console.log(text[0]); // "ש"
console.log(text.charAt(0)); // "ש"
// מציאת מיקום
console.log(text.indexOf("עולם")); // 5
// חיתוך
console.log(text.slice(0, 4)); // "שלום"
console.log(text.substring(5)); // "עולם"
// שינוי אותיות
let eng = "Hello";
console.log(eng.toUpperCase()); // "HELLO"
console.log(eng.toLowerCase()); // "hello"
// החלפה
console.log(text.replace("עולם", "JavaScript")); // "שלום JavaScript"
// פיצול
console.log("א,ב,ג".split(",")); // ["א", "ב", "ג"]
// הסרת רווחים
console.log(" שלום ".trim()); // "שלום"
סיכום
| טיפוס | דוגמה | typeof |
|---|---|---|
| String | "שלום" |
"string" |
| Number | 42, 3.14 |
"number" |
| Boolean | true, false |
"boolean" |
| undefined | undefined |
"undefined" |
| null | null |
"object" |
| Symbol | Symbol() |
"symbol" |
| BigInt | 123n |
"bigint" |
כללי אצבע:
- השתמשו ב-const כברירת מחדל
- השתמשו ב-let רק כשצריך לשנות
- הימנעו מ-var
- השתמשו ב-template literals למחרוזות
אופרטורים (Operators)
אופרטורים הם סמלים שמבצעים פעולות על ערכים. JavaScript מכילה מגוון רחב של אופרטורים.
אופרטורים אריתמטיים (Arithmetic)
פעולות מתמטיות בסיסיות:
let a = 10;
let b = 3;
console.log(a + b); // 13 - חיבור
console.log(a - b); // 7 - חיסור
console.log(a * b); // 30 - כפל
console.log(a / b); // 3.333... - חילוק
console.log(a % b); // 1 - שארית (modulo)
console.log(a ** b); // 1000 - חזקה (10³)
חיבור עם מחרוזות
console.log("שלום" + " " + "עולם"); // "שלום עולם"
console.log("מספר: " + 5); // "מספר: 5"
console.log(5 + "5"); // "55" (מחרוזת!)
console.log(5 - "2"); // 3 (מספר!)
⚠️ זהירות: חיבור עם מחרוזת הופך הכל למחרוזת!
אופרטורי השמה (Assignment)
let x = 10; // השמה בסיסית
x += 5; // x = x + 5 → 15
x -= 3; // x = x - 3 → 12
x *= 2; // x = x * 2 → 24
x /= 4; // x = x / 4 → 6
x %= 4; // x = x % 4 → 2
x **= 3; // x = x ** 3 → 8
טבלת אופרטורי השמה
| אופרטור | דוגמה | שקול ל |
|---|---|---|
= |
x = 5 |
x = 5 |
+= |
x += 5 |
x = x + 5 |
-= |
x -= 5 |
x = x - 5 |
*= |
x *= 5 |
x = x * 5 |
/= |
x /= 5 |
x = x / 5 |
%= |
x %= 5 |
x = x % 5 |
**= |
x **= 5 |
x = x ** 5 |
אופרטורי הגדלה והקטנה (Increment/Decrement)
let count = 5;
count++; // count = count + 1 → 6
count--; // count = count - 1 → 5
// ההבדל בין prefix ל-postfix
let a = 5;
console.log(a++); // 5 (מחזיר ואז מגדיל)
console.log(a); // 6
let b = 5;
console.log(++b); // 6 (מגדיל ואז מחזיר)
console.log(b); // 6
אופרטורי השוואה (Comparison)
מחזירים true או false:
let a = 5;
let b = "5";
// השוואת ערך בלבד (עם המרה)
console.log(a == b); // true (5 == "5")
console.log(a != b); // false
// השוואה מדויקת (ערך וסוג)
console.log(a === b); // false (מספר ≠ מחרוזת)
console.log(a !== b); // true
// השוואות נוספות
console.log(5 > 3); // true - גדול מ
console.log(5 < 3); // false - קטן מ
console.log(5 >= 5); // true - גדול או שווה
console.log(5 <= 4); // false - קטן או שווה
== לעומת === (חשוב!)
// == - השוואה רופפת (עם המרת סוג)
console.log(5 == "5"); // true
console.log(0 == false); // true
console.log(null == undefined); // true
// === - השוואה מדויקת (מומלץ!)
console.log(5 === "5"); // false
console.log(0 === false); // false
console.log(null === undefined); // false
💡 המלצה: תמיד השתמשו ב-
===ו-!==למניעת באגים.
אופרטורים לוגיים (Logical)
&& - וגם (AND)
// מחזיר true רק אם שניהם true
console.log(true && true); // true
console.log(true && false); // false
console.log(false && true); // false
console.log(false && false); // false
// דוגמה מעשית
let age = 25;
let hasLicense = true;
let canDrive = age >= 18 && hasLicense; // true
|| - או (OR)
// מחזיר true אם לפחות אחד true
console.log(true || true); // true
console.log(true || false); // true
console.log(false || true); // true
console.log(false || false); // false
// דוגמה מעשית
let isWeekend = true;
let isHoliday = false;
let dayOff = isWeekend || isHoliday; // true
! - לא (NOT)
// הופך את הערך
console.log(!true); // false
console.log(!false); // true
console.log(!0); // true
console.log(!""); // true
console.log(!"שלום"); // false
// שימוש כפול להמרה לבוליאני
console.log(!!"שלום"); // true
console.log(!!0); // false
?? - Nullish Coalescing
// מחזיר את הערך הימני רק אם השמאלי null או undefined
let name = null;
console.log(name ?? "אנונימי"); // "אנונימי"
let age = 0;
console.log(age ?? 18); // 0 (לא null/undefined)
console.log(age || 18); // 18 (0 הוא falsy!)
אופרטור טרנרי (Ternary)
קיצור ל-if/else בשורה אחת:
// תחביר: condition ? valueIfTrue : valueIfFalse
let age = 20;
let status = age >= 18 ? "בגיר" : "קטין";
console.log(status); // "בגיר"
// דוגמאות נוספות
let score = 75;
let grade = score >= 90 ? "מצוין" :
score >= 70 ? "טוב" :
score >= 55 ? "מספיק" : "נכשל";
console.log(grade); // "טוב"
// שימוש בפונקציות
function greet(name) {
return name ? `שלום ${name}` : "שלום אורח";
}
אופרטורי מחרוזת
// חיבור מחרוזות
let first = "שלום";
let second = "עולם";
let full = first + " " + second; // "שלום עולם"
// קיצור השמה
let text = "שלום";
text += " עולם"; // "שלום עולם"
// template literals
let name = "דן";
let greeting = `שלום ${name}!`; // "שלום דן!"
אופרטור typeof
בודק את סוג הערך:
console.log(typeof 42); // "number"
console.log(typeof "שלום"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (באג!)
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"
סדר קדימויות (Operator Precedence)
כמו במתמטיקה, יש סדר לביצוע פעולות:
// כפל לפני חיבור
console.log(2 + 3 * 4); // 14 (לא 20)
console.log((2 + 3) * 4); // 20
// סדר הקדימויות (מהגבוה לנמוך):
// 1. () - סוגריים
// 2. ** - חזקה
// 3. *, /, % - כפל, חילוק, שארית
// 4. +, - - חיבור, חיסור
// 5. <, >, <=, >= - השוואות
// 6. ==, ===, !=, !== - שוויון
// 7. && - וגם
// 8. || - או
// 9. = - השמה
💡 טיפ: כשיש ספק, השתמשו בסוגריים לבהירות.
דוגמאות מעשיות
חישוב מחיר עם הנחה
let price = 100;
let discount = 20; // אחוז
let finalPrice = price - (price * discount / 100);
console.log(finalPrice); // 80
בדיקת גיל לאתר
let age = 16;
let hasParentPermission = true;
let canEnter = age >= 18 || (age >= 13 && hasParentPermission);
console.log(canEnter); // true
חישוב ממוצע
let scores = [85, 90, 78, 92, 88];
let sum = scores[0] + scores[1] + scores[2] + scores[3] + scores[4];
let average = sum / scores.length;
console.log(average); // 86.6
סיכום
| סוג | אופרטורים |
|---|---|
| אריתמטי | + - * / % ** |
| השמה | = += -= *= /= %= |
| השוואה | == === != !== > < >= <= |
| לוגי | && \|\| ! ?? |
| טרנרי | ? : |
| סוג | typeof |
| הגדלה/הקטנה | ++ -- |
כללי אצבע:
- השתמשו ב-=== במקום ==
- השתמשו ב-?? לבדיקת null/undefined
- השתמשו בסוגריים לבהירות
תנאים (Conditionals)
תנאים מאפשרים לקוד לקבל החלטות ולבצע פעולות שונות בהתאם למצב.
if - תנאי בסיסי
let age = 20;
if (age >= 18) {
console.log("אתה בגיר");
}
מבנה התחביר
if (condition) {
// קוד שירוץ אם התנאי אמת (true)
}
if...else
let age = 15;
if (age >= 18) {
console.log("אתה בגיר");
} else {
console.log("אתה קטין");
}
// פלט: "אתה קטין"
if...else if...else
לבדיקת מספר תנאים:
let score = 75;
if (score >= 90) {
console.log("מצוין");
} else if (score >= 80) {
console.log("טוב מאוד");
} else if (score >= 70) {
console.log("טוב");
} else if (score >= 55) {
console.log("מספיק");
} else {
console.log("נכשל");
}
// פלט: "טוב"
תנאים מקוננים (Nested)
let age = 25;
let hasLicense = true;
if (age >= 18) {
if (hasLicense) {
console.log("אתה יכול לנהוג");
} else {
console.log("צריך רישיון");
}
} else {
console.log("צעיר מדי");
}
גרסה נקייה יותר עם &&
if (age >= 18 && hasLicense) {
console.log("אתה יכול לנהוג");
} else if (age >= 18) {
console.log("צריך רישיון");
} else {
console.log("צעיר מדי");
}
אופרטור טרנרי (Ternary)
קיצור ל-if/else בשורה אחת:
// תחביר: condition ? valueIfTrue : valueIfFalse
let age = 20;
let status = age >= 18 ? "בגיר" : "קטין";
console.log(status); // "בגיר"
// שימוש ישיר
console.log(age >= 18 ? "מותר" : "אסור");
// שרשור (מספר תנאים)
let score = 85;
let grade = score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" :
score >= 60 ? "D" : "F";
switch
לבדיקת ערך מול מספר אפשרויות:
let day = "שני";
switch (day) {
case "ראשון":
console.log("יום ראשון");
break;
case "שני":
console.log("יום שני");
break;
case "שלישי":
console.log("יום שלישי");
break;
default:
console.log("יום אחר");
}
// פלט: "יום שני"
חשיבות break
let num = 2;
// בלי break - ימשיך לכל הcase-ים הבאים!
switch (num) {
case 1:
console.log("אחד");
case 2:
console.log("שתיים");
case 3:
console.log("שלוש");
}
// פלט: "שתיים" ואז "שלוש" (fall-through)
מספר ערכים לאותו קוד
let day = "שבת";
switch (day) {
case "שישי":
case "שבת":
console.log("סוף שבוע!");
break;
default:
console.log("יום עבודה");
}
Truthy ו-Falsy
ב-JavaScript, כל ערך הוא או truthy (נחשב אמת) או falsy (נחשב שקר).
ערכי Falsy (6 ערכים בלבד)
// כל אלה נחשבים false בתנאי:
false
0
"" (מחרוזת ריקה)
null
undefined
NaN
כל השאר הוא Truthy
// כל אלה נחשבים true:
true
1, -1, 3.14 (כל מספר שאינו 0)
"שלום" (כל מחרוזת שאינה ריקה)
"0" (מחרוזת עם אפס)
"false" (מחרוזת)
[] (מערך ריק)
{} (אובייקט ריק)
function() {} (פונקציה)
שימוש מעשי
let name = "";
if (name) {
console.log(`שלום ${name}`);
} else {
console.log("שלום אורח");
}
// פלט: "שלום אורח" (כי "" הוא falsy)
// בדיקה אם מערך לא ריק
let items = [1, 2, 3];
if (items.length) {
console.log(`יש ${items.length} פריטים`);
}
Short-circuit Evaluation
|| - מחזיר את הערך הראשון ה-truthy
let name = "" || "אורח";
console.log(name); // "אורח"
let user = null || undefined || "ברירת מחדל";
console.log(user); // "ברירת מחדל"
// שימוש לערך ברירת מחדל
function greet(name) {
name = name || "אורח";
console.log(`שלום ${name}`);
}
&& - מחזיר את הערך הראשון ה-falsy
let result = "שלום" && "עולם";
console.log(result); // "עולם" (שניהם truthy)
let result2 = "" && "עולם";
console.log(result2); // "" (הראשון falsy)
// שימוש להרצת קוד בתנאי
let user = { name: "דן" };
user && console.log(user.name); // "דן"
let nullUser = null;
nullUser && console.log(nullUser.name); // לא ירוץ
?? - Nullish Coalescing
// מחזיר ימין רק אם שמאל null או undefined
let count = 0;
console.log(count || 10); // 10 (0 הוא falsy!)
console.log(count ?? 10); // 0 (0 אינו null/undefined)
let name = null;
console.log(name ?? "אנונימי"); // "אנונימי"
Optional Chaining (?.)
גישה בטוחה לתכונות מקוננות:
let user = {
name: "דן",
address: {
city: "תל אביב"
}
};
// בלי optional chaining
let city;
if (user && user.address) {
city = user.address.city;
}
// עם optional chaining
let city2 = user?.address?.city; // "תל אביב"
// אם משהו לא קיים
let nullUser = null;
console.log(nullUser?.name); // undefined (ללא שגיאה!)
// עם פונקציות
let result = user.getName?.(); // undefined (אם אין פונקציה)
דוגמאות מעשיות
בדיקת סיסמה
function checkPassword(password) {
if (!password) {
return "נא להזין סיסמה";
}
if (password.length < 8) {
return "הסיסמה קצרה מדי";
}
if (password.length > 20) {
return "הסיסמה ארוכה מדי";
}
return "סיסמה תקינה";
}
תפריט משתמש
let role = "admin";
switch (role) {
case "admin":
console.log("גישה מלאה");
break;
case "editor":
console.log("עריכת תוכן");
break;
case "viewer":
console.log("צפייה בלבד");
break;
default:
console.log("אין הרשאות");
}
חישוב מחיר עם הנחות
function calculatePrice(price, memberType) {
let discount = 0;
if (memberType === "gold") {
discount = 20;
} else if (memberType === "silver") {
discount = 10;
} else if (memberType === "bronze") {
discount = 5;
}
return price - (price * discount / 100);
}
console.log(calculatePrice(100, "gold")); // 80
סיכום
| מבנה | שימוש |
|---|---|
if |
תנאי בסיסי |
if...else |
תנאי עם אלטרנטיבה |
if...else if...else |
מספר תנאים |
? : |
תנאי קצר בשורה אחת |
switch |
בדיקת ערך מול רשימה |
&& |
ריצה בתנאי / ערך ראשון falsy |
\|\| |
ברירת מחדל / ערך ראשון truthy |
?? |
ברירת מחדל ל-null/undefined |
?. |
גישה בטוחה לתכונות |
לולאות (Loops)
לולאות מאפשרות לחזור על פעולות מספר פעמים ללא שכפול קוד.
for - לולאה קלאסית
הלולאה הכי נפוצה, כשיודעים כמה פעמים לחזור.
for (let i = 0; i < 5; i++) {
console.log(i);
}
// פלט: 0, 1, 2, 3, 4
מבנה התחביר
for (initialization; condition; update) {
// קוד שחוזר
}
// initialization - מתבצע פעם אחת בהתחלה
// condition - נבדק לפני כל איטרציה
// update - מתבצע אחרי כל איטרציה
דוגמאות
// ספירה לאחור
for (let i = 5; i >= 1; i--) {
console.log(i);
}
// 5, 4, 3, 2, 1
// קפיצות של 2
for (let i = 0; i <= 10; i += 2) {
console.log(i);
}
// 0, 2, 4, 6, 8, 10
// מעבר על מערך
let fruits = ["תפוח", "בננה", "תפוז"];
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
while - לולאה עם תנאי
ממשיכה כל עוד התנאי אמת.
let count = 0;
while (count < 5) {
console.log(count);
count++;
}
// פלט: 0, 1, 2, 3, 4
מתי להשתמש?
// כשלא יודעים מראש כמה פעמים
let input = "";
while (input !== "יציאה") {
// קבל קלט מהמשתמש
// input = prompt("הכנס טקסט:");
console.log(input);
}
// חיפוש ערך
let numbers = [3, 7, 2, 9, 5];
let i = 0;
while (numbers[i] !== 9) {
i++;
}
console.log(`מצאתי 9 במיקום ${i}`);
⚠️ זהירות: וודאו שהתנאי יהפוך ל-false מתישהו, אחרת תקבלו לולאה אינסופית!
do...while
כמו while, אבל מבצעת לפחות פעם אחת.
let count = 0;
do {
console.log(count);
count++;
} while (count < 5);
// פלט: 0, 1, 2, 3, 4
// ההבדל מ-while:
let x = 10;
while (x < 5) {
console.log("while:", x); // לא ירוץ!
}
do {
console.log("do-while:", x); // ירוץ פעם אחת!
} while (x < 5);
for...of - מעבר על איברים
לולאה מודרנית למעבר על מערכים ומחרוזות.
let fruits = ["תפוח", "בננה", "תפוז"];
for (let fruit of fruits) {
console.log(fruit);
}
// תפוח, בננה, תפוז
// מעבר על מחרוזת
let word = "שלום";
for (let char of word) {
console.log(char);
}
// ש, ל, ו, ם
יתרונות
- קריא יותר
- לא צריך לנהל אינדקס
- עובד על כל iterable
for...in - מעבר על מפתחות
למעבר על מפתחות (keys) של אובייקטים.
let person = {
name: "דן",
age: 25,
city: "תל אביב"
};
for (let key in person) {
console.log(`${key}: ${person[key]}`);
}
// name: דן
// age: 25
// city: תל אביב
// גם עובד על מערכים (מחזיר אינדקסים)
let arr = ["a", "b", "c"];
for (let index in arr) {
console.log(index); // "0", "1", "2" (מחרוזות!)
}
💡 המלצה: השתמשו ב-
for...ofלמערכים ו-for...inלאובייקטים.
break - יציאה מלולאה
עוצר את הלולאה לחלוטין:
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // יציאה מהלולאה
}
console.log(i);
}
// פלט: 0, 1, 2, 3, 4
// חיפוש איבר
let numbers = [3, 7, 2, 9, 5];
let found = false;
for (let num of numbers) {
if (num === 9) {
found = true;
break;
}
}
console.log(found ? "נמצא!" : "לא נמצא");
continue - מעבר לאיטרציה הבאה
מדלג על שאר הקוד באיטרציה הנוכחית:
for (let i = 0; i < 5; i++) {
if (i === 2) {
continue; // מדלג על 2
}
console.log(i);
}
// פלט: 0, 1, 3, 4
// הדפסת מספרים זוגיים בלבד
for (let i = 0; i <= 10; i++) {
if (i % 2 !== 0) {
continue; // מדלג על אי-זוגיים
}
console.log(i);
}
// 0, 2, 4, 6, 8, 10
לולאות מקוננות (Nested)
לולאה בתוך לולאה:
// טבלת כפל
for (let i = 1; i <= 3; i++) {
for (let j = 1; j <= 3; j++) {
console.log(`${i} x ${j} = ${i * j}`);
}
}
// 1x1=1, 1x2=2, 1x3=3, 2x1=2, 2x2=4...
// מעבר על מטריצה
let matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
for (let row of matrix) {
for (let cell of row) {
console.log(cell);
}
}
break/continue בלולאות מקוננות
// break יוצא רק מהלולאה הפנימית
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outer; // יציאה מהלולאה החיצונית
}
console.log(i, j);
}
}
מתודות של מערכים ללולאות
forEach
let fruits = ["תפוח", "בננה", "תפוז"];
fruits.forEach(function(fruit, index) {
console.log(`${index}: ${fruit}`);
});
// 0: תפוח, 1: בננה, 2: תפוז
// עם arrow function
fruits.forEach((fruit) => console.log(fruit));
map
let numbers = [1, 2, 3, 4, 5];
let doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
filter
let numbers = [1, 2, 3, 4, 5, 6];
let evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4, 6]
reduce
let numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 15
דוגמאות מעשיות
מציאת ערך מקסימלי
let numbers = [23, 55, 12, 89, 34];
let max = numbers[0];
for (let num of numbers) {
if (num > max) {
max = num;
}
}
console.log(max); // 89
ספירת תווים
let text = "שלום עולם";
let count = 0;
for (let char of text) {
if (char !== " ") {
count++;
}
}
console.log(`מספר תווים: ${count}`); // 8
הפיכת מערך
let arr = [1, 2, 3, 4, 5];
let reversed = [];
for (let i = arr.length - 1; i >= 0; i--) {
reversed.push(arr[i]);
}
console.log(reversed); // [5, 4, 3, 2, 1]
סכום מספרים זוגיים
let sum = 0;
for (let i = 2; i <= 100; i += 2) {
sum += i;
}
console.log(sum); // 2550
השוואת סוגי לולאות
| לולאה | שימוש | דוגמה |
|---|---|---|
for |
כשיודעים כמה איטרציות | for (let i = 0; i < 10; i++) |
while |
כשהתנאי לא ידוע מראש | while (input !== "exit") |
do...while |
ריצה אחת לפחות | do { ... } while (x > 0) |
for...of |
מעבר על ערכים במערך | for (let item of arr) |
for...in |
מעבר על מפתחות באובייקט | for (let key in obj) |
forEach |
מעבר על מערך (מתודה) | arr.forEach(item => ...) |
סיכום
כללי אצבע:
- השתמשו ב-for...of למערכים
- השתמשו ב-for...in לאובייקטים
- השתמשו ב-for קלאסי כשצריך אינדקס
- השתמשו ב-while כשלא יודעים כמה איטרציות
- זכרו לעדכן את התנאי למניעת לולאה אינסופית
פונקציות (Functions)
פונקציה היא בלוק קוד שניתן לקרוא לו בשם ולהשתמש בו שוב ושוב.
הכרזה על פונקציה (Function Declaration)
// הגדרת הפונקציה
function sayHello() {
console.log("שלום!");
}
// קריאה לפונקציה
sayHello(); // "שלום!"
sayHello(); // "שלום!" (אפשר לקרוא שוב ושוב)
מבנה התחביר
function functionName(parameters) {
// גוף הפונקציה
// קוד שמתבצע כשקוראים לפונקציה
}
פרמטרים (Parameters)
פרמטרים הם ערכים שהפונקציה מקבלת:
function greet(name) {
console.log(`שלום ${name}!`);
}
greet("דן"); // "שלום דן!"
greet("דנה"); // "שלום דנה!"
// מספר פרמטרים
function add(a, b) {
console.log(a + b);
}
add(5, 3); // 8
פרמטרים עם ברירת מחדל
function greet(name = "אורח") {
console.log(`שלום ${name}!`);
}
greet("דן"); // "שלום דן!"
greet(); // "שלום אורח!"
ערך מוחזר (Return)
פונקציות יכולות להחזיר ערך:
function add(a, b) {
return a + b;
}
let result = add(5, 3);
console.log(result); // 8
// שימוש ישיר בתוצאה
console.log(add(10, 20)); // 30
console.log(add(2, 3) * 2); // 10
return עוצר את הפונקציה
function checkAge(age) {
if (age < 0) {
return "גיל לא תקין"; // הפונקציה נעצרת כאן
}
if (age < 18) {
return "קטין";
}
return "בגיר";
}
console.log(checkAge(-5)); // "גיל לא תקין"
console.log(checkAge(15)); // "קטין"
console.log(checkAge(25)); // "בגיר"
פונקציה ללא return מחזירה undefined
function doSomething() {
console.log("עושה משהו");
// אין return
}
let result = doSomething();
console.log(result); // undefined
Function Expression
דרך נוספת להגדיר פונקציה - כערך במשתנה:
const greet = function(name) {
return `שלום ${name}!`;
};
console.log(greet("דן")); // "שלום דן!"
ההבדל מ-Declaration
// Declaration - אפשר לקרוא לפני ההגדרה (hoisting)
sayHi(); // עובד!
function sayHi() {
console.log("היי!");
}
// Expression - אי אפשר לקרוא לפני ההגדרה
sayBye(); // ❌ שגיאה!
const sayBye = function() {
console.log("ביי!");
};
Arrow Functions (=>)
תחביר מקוצר ומודרני לפונקציות:
// פונקציה רגילה
const add = function(a, b) {
return a + b;
};
// Arrow function
const addArrow = (a, b) => {
return a + b;
};
// קיצור נוסף - return מרומז
const addShort = (a, b) => a + b;
console.log(addShort(5, 3)); // 8
כללי קיצור
// פרמטר אחד - אפשר בלי סוגריים
const double = x => x * 2;
// אפס פרמטרים - חייבים סוגריים ריקות
const sayHi = () => "היי!";
// גוף מרובה שורות - חייבים {} ו-return מפורש
const greet = (name) => {
const message = `שלום ${name}`;
return message + "!";
};
// החזרת אובייקט - חייבים סוגריים
const createUser = (name) => ({ name: name, active: true });
Callback Functions
פונקציה שמועברת כפרמטר לפונקציה אחרת:
function processData(data, callback) {
console.log("מעבד נתונים...");
const result = data * 2;
callback(result); // קריאה לפונקציה שהועברה
}
function showResult(value) {
console.log(`התוצאה: ${value}`);
}
processData(5, showResult); // "מעבד נתונים..." → "התוצאה: 10"
// עם arrow function
processData(10, (result) => console.log(result)); // 20
שימוש נפוץ ב-callbacks
// setTimeout - הרצה אחרי זמן
setTimeout(() => {
console.log("עברו 2 שניות");
}, 2000);
// forEach - עבור כל איבר
[1, 2, 3].forEach(num => console.log(num));
// map - המרה
const doubled = [1, 2, 3].map(num => num * 2);
Scope (טווח)
Block Scope
function example() {
let x = 10; // נגיש רק בתוך הפונקציה
if (true) {
let y = 20; // נגיש רק בתוך ה-if
console.log(x); // ✅ 10
console.log(y); // ✅ 20
}
console.log(x); // ✅ 10
console.log(y); // ❌ שגיאה! y לא קיים כאן
}
Global Scope
let globalVar = "אני גלובלי";
function test() {
console.log(globalVar); // ✅ נגיש
}
test(); // "אני גלובלי"
Closure
function outer() {
let count = 0;
return function inner() {
count++;
return count;
};
}
const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// inner "זוכרת" את count מ-outer
Hoisting
JavaScript מעלה הכרזות לתחילת הסקופ:
// Function Declaration - מועלת לגמרי
sayHello(); // ✅ עובד!
function sayHello() {
console.log("שלום!");
}
// Function Expression - רק המשתנה מועלה
sayBye(); // ❌ שגיאה!
var sayBye = function() {
console.log("ביי!");
};
// let/const לא מועלים (זמינים רק אחרי ההכרזה)
console.log(x); // ❌ שגיאה!
let x = 5;
Rest Parameters (...)
קבלת מספר לא מוגבל של פרמטרים:
function sum(...numbers) {
let total = 0;
for (let num of numbers) {
total += num;
}
return total;
}
console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3, 4)); // 10
console.log(sum()); // 0
// עם פרמטרים נוספים
function greetAll(greeting, ...names) {
for (let name of names) {
console.log(`${greeting} ${name}!`);
}
}
greetAll("שלום", "דן", "דנה", "אבי");
Spread Operator (...)
פריסת מערך לפרמטרים:
function add(a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
console.log(add(...numbers)); // 6 (במקום add(1, 2, 3))
// שימוש עם Math
const values = [5, 2, 8, 1];
console.log(Math.max(...values)); // 8
console.log(Math.min(...values)); // 1
פונקציות פנימיות מובנות
Math
Math.round(4.7); // 5 (עיגול)
Math.floor(4.7); // 4 (עיגול למטה)
Math.ceil(4.2); // 5 (עיגול למעלה)
Math.abs(-5); // 5 (ערך מוחלט)
Math.random(); // מספר אקראי 0-1
Math.max(1, 5, 3); // 5
Math.min(1, 5, 3); // 1
Math.sqrt(16); // 4 (שורש)
Math.pow(2, 3); // 8 (חזקה)
String
"hello".toUpperCase(); // "HELLO"
"HELLO".toLowerCase(); // "hello"
"hello".includes("ell"); // true
"hello".startsWith("he"); // true
"hello".slice(0, 2); // "he"
"a,b,c".split(","); // ["a", "b", "c"]
Number
parseInt("42"); // 42
parseFloat("3.14"); // 3.14
(3.14159).toFixed(2); // "3.14"
Number.isInteger(5); // true
Number.isNaN(NaN); // true
דוגמאות מעשיות
פונקציית חישוב מחיר
function calculateTotal(price, quantity = 1, discount = 0) {
const subtotal = price * quantity;
const discountAmount = subtotal * (discount / 100);
return subtotal - discountAmount;
}
console.log(calculateTotal(100)); // 100
console.log(calculateTotal(100, 3)); // 300
console.log(calculateTotal(100, 3, 10)); // 270
פונקציית אימות אימייל
const isValidEmail = (email) => {
return email.includes("@") && email.includes(".");
};
console.log(isValidEmail("[email protected]")); // true
console.log(isValidEmail("invalid")); // false
מחולל סיסמאות
function generatePassword(length = 8) {
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
let password = "";
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * chars.length);
password += chars[randomIndex];
}
return password;
}
console.log(generatePassword()); // "x7k2m9p1"
console.log(generatePassword(12)); // "a3b5c7d9e1f2"
סיכום
| סוג | תחביר | דוגמה |
|---|---|---|
| Declaration | function name() {} |
function add(a, b) { return a + b; } |
| Expression | const name = function() {} |
const add = function(a, b) { return a + b; }; |
| Arrow | const name = () => {} |
const add = (a, b) => a + b; |
| Callback | פונקציה כפרמטר | arr.map(x => x * 2) |
כללי אצבע: - השתמשו בשמות תיאוריים לפונקציות - פונקציה צריכה לעשות דבר אחד - השתמשו בערכי ברירת מחדל - החזירו ערך במקום לשנות משתנים גלובליים - Arrow functions מצוינות ל-callbacks קצרים
מערכים (Arrays)
מערך הוא רשימה מסודרת של ערכים. אחד ממבני הנתונים החשובים ביותר ב-JavaScript.
יצירת מערך
// שיטה 1: סוגריים מרובעות (נפוץ)
let fruits = ["תפוח", "בננה", "תפוז"];
// שיטה 2: constructor (פחות נפוץ)
let numbers = new Array(1, 2, 3);
// מערך ריק
let empty = [];
// מערך עם סוגים מעורבים
let mixed = [1, "שלום", true, null, { name: "דן" }];
גישה לאיברים
מערכים מתחילים מאינדקס 0:
let fruits = ["תפוח", "בננה", "תפוז"];
console.log(fruits[0]); // "תפוח"
console.log(fruits[1]); // "בננה"
console.log(fruits[2]); // "תפוז"
console.log(fruits[3]); // undefined (לא קיים)
// האיבר האחרון
console.log(fruits[fruits.length - 1]); // "תפוז"
// שינוי ערך
fruits[1] = "מנגו";
console.log(fruits); // ["תפוח", "מנגו", "תפוז"]
אורך המערך (length)
let fruits = ["תפוח", "בננה", "תפוז"];
console.log(fruits.length); // 3
// שימוש בלולאה
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
הוספה והסרה של איברים
push - הוספה לסוף
let fruits = ["תפוח", "בננה"];
fruits.push("תפוז");
console.log(fruits); // ["תפוח", "בננה", "תפוז"]
// אפשר להוסיף כמה בבת אחת
fruits.push("מנגו", "ענבים");
pop - הסרה מהסוף
let fruits = ["תפוח", "בננה", "תפוז"];
let removed = fruits.pop();
console.log(removed); // "תפוז"
console.log(fruits); // ["תפוח", "בננה"]
unshift - הוספה להתחלה
let fruits = ["בננה", "תפוז"];
fruits.unshift("תפוח");
console.log(fruits); // ["תפוח", "בננה", "תפוז"]
shift - הסרה מההתחלה
let fruits = ["תפוח", "בננה", "תפוז"];
let removed = fruits.shift();
console.log(removed); // "תפוח"
console.log(fruits); // ["בננה", "תפוז"]
splice - הוספה/הסרה ממיקום ספציפי
// התחביר: array.splice(start, deleteCount, items...)
let fruits = ["תפוח", "בננה", "תפוז", "מנגו"];
// הסרת 2 איברים מאינדקס 1
let removed = fruits.splice(1, 2);
console.log(removed); // ["בננה", "תפוז"]
console.log(fruits); // ["תפוח", "מנגו"]
// הוספה מבלי להסיר
fruits.splice(1, 0, "אבטיח");
console.log(fruits); // ["תפוח", "אבטיח", "מנגו"]
// החלפה
fruits.splice(1, 1, "ענבים", "אננס");
console.log(fruits); // ["תפוח", "ענבים", "אננס", "מנגו"]
slice - חיתוך (ללא שינוי המקור)
let fruits = ["תפוח", "בננה", "תפוז", "מנגו", "ענבים"];
// מאינדקס 1 עד 3 (לא כולל)
let sliced = fruits.slice(1, 3);
console.log(sliced); // ["בננה", "תפוז"]
console.log(fruits); // לא השתנה!
// מאינדקס 2 עד הסוף
console.log(fruits.slice(2)); // ["תפוז", "מנגו", "ענבים"]
// שלילי - מהסוף
console.log(fruits.slice(-2)); // ["מנגו", "ענבים"]
// העתקת מערך
let copy = fruits.slice();
חיפוש במערך
indexOf - מיקום ראשון
let fruits = ["תפוח", "בננה", "תפוז", "בננה"];
console.log(fruits.indexOf("בננה")); // 1
console.log(fruits.indexOf("מנגו")); // -1 (לא נמצא)
lastIndexOf - מיקום אחרון
let fruits = ["תפוח", "בננה", "תפוז", "בננה"];
console.log(fruits.lastIndexOf("בננה")); // 3
includes - האם קיים
let fruits = ["תפוח", "בננה", "תפוז"];
console.log(fruits.includes("בננה")); // true
console.log(fruits.includes("מנגו")); // false
find - מציאת איבר לפי תנאי
let numbers = [5, 12, 8, 130, 44];
let found = numbers.find(num => num > 10);
console.log(found); // 12 (הראשון שעונה על התנאי)
// עם אובייקטים
let users = [
{ id: 1, name: "דן" },
{ id: 2, name: "דנה" }
];
let user = users.find(u => u.id === 2);
console.log(user); // { id: 2, name: "דנה" }
findIndex - אינדקס לפי תנאי
let numbers = [5, 12, 8, 130, 44];
let index = numbers.findIndex(num => num > 10);
console.log(index); // 1
מתודות לולאה
forEach - מעבר על כל איבר
let fruits = ["תפוח", "בננה", "תפוז"];
fruits.forEach((fruit, index) => {
console.log(`${index}: ${fruit}`);
});
// 0: תפוח
// 1: בננה
// 2: תפוז
map - יצירת מערך חדש מהמרה
let numbers = [1, 2, 3, 4, 5];
let doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// המערך המקורי לא משתנה
console.log(numbers); // [1, 2, 3, 4, 5]
filter - סינון לפי תנאי
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4, 6, 8, 10]
let bigNumbers = numbers.filter(num => num > 5);
console.log(bigNumbers); // [6, 7, 8, 9, 10]
reduce - צבירה לערך יחיד
let numbers = [1, 2, 3, 4, 5];
// סכום
let sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 15
// מקסימום
let max = numbers.reduce((acc, num) => num > acc ? num : acc);
console.log(max); // 5
// ספירה
let words = ["שלום", "עולם", "שלום", "לכולם"];
let count = words.reduce((acc, word) => {
acc[word] = (acc[word] || 0) + 1;
return acc;
}, {});
console.log(count); // { שלום: 2, עולם: 1, לכולם: 1 }
some - האם לפחות אחד עונה על התנאי
let numbers = [1, 2, 3, 4, 5];
console.log(numbers.some(num => num > 4)); // true
console.log(numbers.some(num => num > 10)); // false
every - האם כולם עונים על התנאי
let numbers = [2, 4, 6, 8];
console.log(numbers.every(num => num % 2 === 0)); // true
console.log(numbers.every(num => num > 5)); // false
מיון (sort)
// מיון אלפביתי
let fruits = ["תפוז", "בננה", "תפוח"];
fruits.sort();
console.log(fruits); // ["בננה", "תפוז", "תפוח"]
// מיון מספרי - צריך פונקציית השוואה!
let numbers = [30, 4, 100, 21];
numbers.sort();
console.log(numbers); // ❌ [100, 21, 30, 4] (מיון כמחרוזות!)
numbers.sort((a, b) => a - b);
console.log(numbers); // ✅ [4, 21, 30, 100] (עולה)
numbers.sort((a, b) => b - a);
console.log(numbers); // ✅ [100, 30, 21, 4] (יורד)
הפיכה (reverse)
let numbers = [1, 2, 3, 4, 5];
numbers.reverse();
console.log(numbers); // [5, 4, 3, 2, 1]
חיבור מערכים
concat
let arr1 = [1, 2];
let arr2 = [3, 4];
let combined = arr1.concat(arr2);
console.log(combined); // [1, 2, 3, 4]
spread operator
let arr1 = [1, 2];
let arr2 = [3, 4];
let combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4]
// עם ערכים נוספים
let extra = [0, ...arr1, 2.5, ...arr2, 5];
console.log(extra); // [0, 1, 2, 2.5, 3, 4, 5]
המרה למחרוזת (join)
let fruits = ["תפוח", "בננה", "תפוז"];
console.log(fruits.join()); // "תפוח,בננה,תפוז"
console.log(fruits.join(" ")); // "תפוח בננה תפוז"
console.log(fruits.join(" - ")); // "תפוח - בננה - תפוז"
Destructuring
פירוק מערך למשתנים:
let fruits = ["תפוח", "בננה", "תפוז"];
// במקום:
// let first = fruits[0];
// let second = fruits[1];
// אפשר:
let [first, second] = fruits;
console.log(first); // "תפוח"
console.log(second); // "בננה"
// דילוג על ערכים
let [a, , c] = fruits;
console.log(c); // "תפוז"
// עם spread
let [head, ...rest] = fruits;
console.log(head); // "תפוח"
console.log(rest); // ["בננה", "תפוז"]
דוגמאות מעשיות
מציאת ממוצע
const average = (arr) => {
const sum = arr.reduce((acc, num) => acc + num, 0);
return sum / arr.length;
};
console.log(average([80, 90, 70, 85])); // 81.25
הסרת כפילויות
const unique = (arr) => [...new Set(arr)];
console.log(unique([1, 2, 2, 3, 3, 3])); // [1, 2, 3]
השטחת מערך
const nested = [[1, 2], [3, 4], [5, 6]];
const flat = nested.flat();
console.log(flat); // [1, 2, 3, 4, 5, 6]
סיכום מתודות
| פעולה | מתודה | משנה מקור? |
|---|---|---|
| הוספה לסוף | push() |
✅ |
| הסרה מסוף | pop() |
✅ |
| הוספה להתחלה | unshift() |
✅ |
| הסרה מהתחלה | shift() |
✅ |
| הוספה/הסרה ממיקום | splice() |
✅ |
| חיתוך | slice() |
❌ |
| מיון | sort() |
✅ |
| הפיכה | reverse() |
✅ |
| המרה | map() |
❌ |
| סינון | filter() |
❌ |
| צבירה | reduce() |
❌ |
| חיפוש | find() |
❌ |
| חיבור | concat() |
❌ |
אובייקטים (Objects)
אובייקט הוא אוסף של מאפיינים (properties) ומתודות (methods) המתארים ישות אחת.
יצירת אובייקט
Object Literal (נפוץ ביותר)
const person = {
name: "דן",
age: 25,
city: "תל אביב"
};
מאפיינים עם שמות מיוחדים
const obj = {
"first name": "דן", // רווח - חייבים גרשיים
"my-key": "value", // מקף
123: "מספר כמפתח" // מספר
};
גישה למאפיינים
Dot Notation (נקודה)
const person = {
name: "דן",
age: 25
};
console.log(person.name); // "דן"
console.log(person.age); // 25
Bracket Notation (סוגריים)
console.log(person["name"]); // "דן"
// חובה עבור שמות מיוחדים
const obj = { "first name": "דן" };
console.log(obj["first name"]); // "דן"
// שימושי עם משתנים
const key = "name";
console.log(person[key]); // "דן"
שינוי והוספת מאפיינים
const person = {
name: "דן"
};
// שינוי ערך קיים
person.name = "דנה";
// הוספת מאפיין חדש
person.age = 25;
person["city"] = "תל אביב";
console.log(person);
// { name: "דנה", age: 25, city: "תל אביב" }
מחיקת מאפיין
const person = {
name: "דן",
age: 25,
city: "תל אביב"
};
delete person.city;
console.log(person); // { name: "דן", age: 25 }
מתודות (Methods)
מתודה היא פונקציה שמוגדרת בתוך אובייקט:
const person = {
name: "דן",
age: 25,
// מתודה
greet: function() {
console.log("שלום!");
},
// קיצור מודרני
sayAge() {
console.log(`אני בן ${this.age}`);
}
};
person.greet(); // "שלום!"
person.sayAge(); // "אני בן 25"
this
המילה this מתייחסת לאובייקט שבו נמצאת המתודה:
const person = {
name: "דן",
age: 25,
introduce() {
console.log(`שמי ${this.name} ואני בן ${this.age}`);
}
};
person.introduce(); // "שמי דן ואני בן 25"
זהירות עם Arrow Functions!
const person = {
name: "דן",
// ❌ Arrow function - this לא עובד כמצופה!
greetArrow: () => {
console.log(this.name); // undefined
},
// ✅ פונקציה רגילה
greetRegular() {
console.log(this.name); // "דן"
}
};
בדיקת קיום מאפיין
const person = {
name: "דן",
age: 25
};
// אופרטור in
console.log("name" in person); // true
console.log("city" in person); // false
// hasOwnProperty
console.log(person.hasOwnProperty("name")); // true
// בדיקת ערך
console.log(person.city !== undefined); // true אם קיים
מעבר על אובייקט
for...in
const person = {
name: "דן",
age: 25,
city: "תל אביב"
};
for (let key in person) {
console.log(`${key}: ${person[key]}`);
}
// name: דן
// age: 25
// city: תל אביב
Object.keys - רשימת מפתחות
const keys = Object.keys(person);
console.log(keys); // ["name", "age", "city"]
Object.values - רשימת ערכים
const values = Object.values(person);
console.log(values); // ["דן", 25, "תל אביב"]
Object.entries - זוגות [key, value]
const entries = Object.entries(person);
console.log(entries);
// [["name", "דן"], ["age", 25], ["city", "תל אביב"]]
// שימוש בלולאה
for (let [key, value] of Object.entries(person)) {
console.log(`${key}: ${value}`);
}
Destructuring
פירוק אובייקט למשתנים:
const person = {
name: "דן",
age: 25,
city: "תל אביב"
};
// במקום:
// const name = person.name;
// const age = person.age;
// אפשר:
const { name, age } = person;
console.log(name); // "דן"
console.log(age); // 25
// עם שינוי שם
const { name: userName, age: userAge } = person;
console.log(userName); // "דן"
// עם ברירת מחדל
const { country = "ישראל" } = person;
console.log(country); // "ישראל"
// אובייקטים מקוננים
const user = {
name: "דן",
address: {
city: "תל אביב",
street: "רוטשילד"
}
};
const { address: { city } } = user;
console.log(city); // "תל אביב"
Spread Operator
העתקת אובייקט
const original = { a: 1, b: 2 };
const copy = { ...original };
copy.a = 99;
console.log(original.a); // 1 (לא השתנה)
מיזוג אובייקטים
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 2, c: 3, d: 4 }
// עם override
const defaults = { color: "blue", size: "medium" };
const userSettings = { size: "large" };
const settings = { ...defaults, ...userSettings };
console.log(settings); // { color: "blue", size: "large" }
Shorthand Properties
const name = "דן";
const age = 25;
// במקום:
const person1 = { name: name, age: age };
// אפשר:
const person2 = { name, age };
console.log(person2); // { name: "דן", age: 25 }
Computed Property Names
const key = "dynamicKey";
const obj = {
[key]: "ערך דינמי",
[`prefix_${key}`]: "עם prefix"
};
console.log(obj.dynamicKey); // "ערך דינמי"
console.log(obj.prefix_dynamicKey); // "עם prefix"
Object.assign
העתקה ומיזוג של אובייקטים:
const target = { a: 1 };
const source = { b: 2, c: 3 };
Object.assign(target, source);
console.log(target); // { a: 1, b: 2, c: 3 }
// יצירת עותק
const copy = Object.assign({}, target);
Object.freeze ו-Object.seal
// freeze - לא ניתן לשנות, להוסיף או למחוק
const frozen = Object.freeze({ a: 1 });
frozen.a = 2; // ❌ לא יעבוד
frozen.b = 3; // ❌ לא יעבוד
delete frozen.a; // ❌ לא יעבוד
// seal - ניתן לשנות, לא להוסיף או למחוק
const sealed = Object.seal({ a: 1 });
sealed.a = 2; // ✅ עובד
sealed.b = 3; // ❌ לא יעבוד
delete sealed.a; // ❌ לא יעבוד
אובייקטים מקוננים
const company = {
name: "TechCorp",
employees: [
{ name: "דן", role: "developer" },
{ name: "דנה", role: "designer" }
],
address: {
city: "תל אביב",
street: "רוטשילד",
number: 42
}
};
// גישה
console.log(company.address.city); // "תל אביב"
console.log(company.employees[0].name); // "דן"
// Optional Chaining
console.log(company.address?.zipCode); // undefined (בלי שגיאה)
דוגמאות מעשיות
יצירת user factory
function createUser(name, age) {
return {
name,
age,
isAdult() {
return this.age >= 18;
},
greet() {
return `שלום, אני ${this.name}`;
}
};
}
const user = createUser("דן", 25);
console.log(user.greet()); // "שלום, אני דן"
console.log(user.isAdult()); // true
עדכון מאפיין בצורה אימטבילית
const user = { name: "דן", age: 25 };
// יצירת עותק עם שינוי
const updatedUser = { ...user, age: 26 };
console.log(user.age); // 25 (לא השתנה)
console.log(updatedUser.age); // 26
סיכום
| פעולה | תחביר |
|---|---|
| יצירה | { key: value } |
| גישה | obj.key או obj["key"] |
| הוספה/שינוי | obj.key = value |
| מחיקה | delete obj.key |
| בדיקת קיום | "key" in obj |
| מפתחות | Object.keys(obj) |
| ערכים | Object.values(obj) |
| זוגות | Object.entries(obj) |
| פירוק | const { key } = obj |
| פריסה | { ...obj } |
DOM - Document Object Model
ה-DOM הוא ייצוג של דף ה-HTML כמבנה עץ שאפשר לגשת אליו ולשנות אותו עם JavaScript.
מה זה DOM?
כשדפדפן טוען דף HTML, הוא יוצר מודל אובייקטים:
document
└── html
├── head
│ └── title
└── body
├── h1
├── div
│ └── p
└── button
JavaScript יכולה לגשת לכל אלמנט ולשנות אותו!
בחירת אלמנטים
לפי ID (יחיד)
const element = document.getElementById("myId");
console.log(element);
<div id="myId">תוכן</div>
לפי Class (רשימה)
const elements = document.getElementsByClassName("myClass");
console.log(elements); // HTMLCollection
// גישה לאיבר ספציפי
console.log(elements[0]);
לפי תגית (רשימה)
const paragraphs = document.getElementsByTagName("p");
לפי Selector (מודרני - מומלץ!)
// בחירת אלמנט אחד (הראשון)
const element = document.querySelector(".myClass");
const header = document.querySelector("#header");
const firstP = document.querySelector("div p");
// בחירת כל האלמנטים
const allButtons = document.querySelectorAll("button");
const allItems = document.querySelectorAll(".item");
// מעבר על התוצאות
allButtons.forEach(btn => {
console.log(btn.textContent);
});
שינוי תוכן
textContent - טקסט בלבד
const element = document.querySelector("#title");
// קריאה
console.log(element.textContent);
// שינוי
element.textContent = "כותרת חדשה";
innerHTML - עם HTML
const container = document.querySelector("#container");
// הוספת HTML
container.innerHTML = "<strong>טקסט מודגש</strong>";
// תוספת לקיים
container.innerHTML += "<p>פסקה חדשה</p>";
⚠️ זהירות:
innerHTMLיכול להיות מסוכן אם מכניסים קלט משתמש (XSS)!
innerText
// דומה ל-textContent אבל מתחשב ב-CSS
element.innerText = "טקסט שייראה";
שינוי סגנון (Style)
const box = document.querySelector("#box");
// שינוי style יחיד
box.style.backgroundColor = "blue";
box.style.fontSize = "20px";
box.style.padding = "10px";
box.style.borderRadius = "5px";
// שים לב: camelCase במקום kebab-case
// CSS: background-color → JS: backgroundColor
// CSS: font-size → JS: fontSize
שינוי Classes
const element = document.querySelector("#element");
// הוספת class
element.classList.add("active");
// הסרת class
element.classList.remove("active");
// החלפה (toggle)
element.classList.toggle("active");
// בדיקה
if (element.classList.contains("active")) {
console.log("האלמנט פעיל");
}
// החלפת class אחד באחר
element.classList.replace("old", "new");
שינוי Attributes
const link = document.querySelector("a");
// קריאת attribute
console.log(link.getAttribute("href"));
// שינוי/הוספת attribute
link.setAttribute("href", "https://google.com");
link.setAttribute("target", "_blank");
// הסרת attribute
link.removeAttribute("target");
// בדיקה
if (link.hasAttribute("href")) {
console.log("יש href");
}
תכונות נפוצות
const img = document.querySelector("img");
img.src = "image.jpg";
img.alt = "תיאור התמונה";
const input = document.querySelector("input");
input.value = "ערך חדש";
input.placeholder = "הכנס טקסט";
input.disabled = true;
const checkbox = document.querySelector('input[type="checkbox"]');
checkbox.checked = true;
יצירת אלמנטים חדשים
// יצירת אלמנט
const newDiv = document.createElement("div");
newDiv.textContent = "אני div חדש!";
newDiv.className = "box";
newDiv.id = "newBox";
// הוספה לדף
document.body.appendChild(newDiv);
// הוספה לאלמנט ספציפי
const container = document.querySelector("#container");
container.appendChild(newDiv);
הוספה במיקום ספציפי
const parent = document.querySelector("#parent");
const newElement = document.createElement("li");
newElement.textContent = "פריט חדש";
// בסוף
parent.appendChild(newElement);
// בהתחלה
parent.prepend(newElement);
// לפני אלמנט ספציפי
const reference = parent.querySelector(".specific");
parent.insertBefore(newElement, reference);
// אחרי אלמנט ספציפי
reference.after(newElement);
// לפני אלמנט ספציפי
reference.before(newElement);
הסרת אלמנטים
const element = document.querySelector("#toRemove");
// שיטה 1: remove() (מודרני)
element.remove();
// שיטה 2: דרך ההורה
const parent = document.querySelector("#parent");
parent.removeChild(element);
שכפול אלמנט
const original = document.querySelector("#original");
// שכפול ללא ילדים
const shallowClone = original.cloneNode(false);
// שכפול עם כל הילדים
const deepClone = original.cloneNode(true);
document.body.appendChild(deepClone);
ניווט בעץ ה-DOM
const element = document.querySelector("#element");
// הורה
element.parentElement;
element.parentNode;
// ילדים
element.children; // HTMLCollection של אלמנטים
element.childNodes; // NodeList כולל טקסט
element.firstElementChild;
element.lastElementChild;
// אחים
element.nextElementSibling;
element.previousElementSibling;
דוגמה מלאה
HTML
<!DOCTYPE html>
<html>
<head>
<title>דוגמת DOM</title>
<style>
.highlight { background-color: yellow; }
.hidden { display: none; }
</style>
</head>
<body>
<h1 id="title">כותרת</h1>
<ul id="list">
<li>פריט 1</li>
<li>פריט 2</li>
</ul>
<button id="addBtn">הוסף פריט</button>
<button id="toggleBtn">הסתר/הצג רשימה</button>
<script src="app.js"></script>
</body>
</html>
JavaScript
// בחירת אלמנטים
const title = document.querySelector("#title");
const list = document.querySelector("#list");
const addBtn = document.querySelector("#addBtn");
const toggleBtn = document.querySelector("#toggleBtn");
// שינוי כותרת
title.textContent = "רשימת הפריטים שלי";
title.style.color = "blue";
// הוספת פריט חדש
addBtn.addEventListener("click", () => {
const newItem = document.createElement("li");
const itemCount = list.children.length + 1;
newItem.textContent = `פריט ${itemCount}`;
list.appendChild(newItem);
});
// הסתרה/הצגה של הרשימה
toggleBtn.addEventListener("click", () => {
list.classList.toggle("hidden");
});
// הדגשה בלחיצה על פריט
list.addEventListener("click", (e) => {
if (e.target.tagName === "LI") {
e.target.classList.toggle("highlight");
}
});
טיפים חשובים
1. ממתינים שהדף ייטען
<!-- אפשרות 1: script בסוף -->
<body>
<!-- תוכן -->
<script src="app.js"></script>
</body>
<!-- אפשרות 2: defer -->
<head>
<script src="app.js" defer></script>
</head>
<!-- אפשרות 3: DOMContentLoaded -->
<script>
document.addEventListener("DOMContentLoaded", () => {
// הקוד שלך כאן
});
</script>
2. ביצועים
// ❌ לא יעיל - גורם לreflow בכל איטרציה
for (let i = 0; i < 100; i++) {
document.body.innerHTML += `<div>${i}</div>`;
}
// ✅ יעיל - שינוי אחד
let html = "";
for (let i = 0; i < 100; i++) {
html += `<div>${i}</div>`;
}
document.body.innerHTML = html;
// ✅ יעיל יותר - DocumentFragment
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const div = document.createElement("div");
div.textContent = i;
fragment.appendChild(div);
}
document.body.appendChild(fragment);
סיכום
| פעולה | מתודה |
|---|---|
| בחירה לפי ID | getElementById("id") |
| בחירה לפי selector | querySelector("selector") |
| בחירת כולם | querySelectorAll("selector") |
| שינוי טקסט | element.textContent = "..." |
| שינוי HTML | element.innerHTML = "..." |
| שינוי סגנון | element.style.property = "..." |
| הוספת class | element.classList.add("...") |
| יצירת אלמנט | document.createElement("tag") |
| הוספה לדף | parent.appendChild(element) |
| הסרה | element.remove() |
אירועים (Events)
אירועים הם פעולות שקורות בדף - לחיצות, הקלדות, תנועות עכבר ועוד. JavaScript מאפשרת להגיב לאירועים אלה.
מה זה אירוע?
אירוע הוא כל פעולה שקורית בדף: - לחיצת עכבר - הקלדה במקלדת - טעינת הדף - הזזת העכבר - שינוי גודל החלון - ועוד...
הוספת Event Listener
addEventListener (מומלץ!)
const button = document.querySelector("#myButton");
button.addEventListener("click", function() {
console.log("לחצת על הכפתור!");
});
// עם arrow function
button.addEventListener("click", () => {
console.log("לחצת על הכפתור!");
});
// עם פונקציה נפרדת
function handleClick() {
console.log("לחצת על הכפתור!");
}
button.addEventListener("click", handleClick);
שיטות ישנות (פחות מומלצות)
// onclick property
button.onclick = function() {
console.log("לחצת!");
};
// inline HTML (לא מומלץ!)
// <button onclick="handleClick()">לחץ</button>
סוגי אירועים נפוצים
אירועי עכבר
element.addEventListener("click", handler); // לחיצה
element.addEventListener("dblclick", handler); // לחיצה כפולה
element.addEventListener("mouseenter", handler); // עכבר נכנס
element.addEventListener("mouseleave", handler); // עכבר יוצא
element.addEventListener("mousemove", handler); // עכבר זז
element.addEventListener("mousedown", handler); // לחצן עכבר נלחץ
element.addEventListener("mouseup", handler); // לחצן עכבר שוחרר
אירועי מקלדת
document.addEventListener("keydown", handler); // מקש נלחץ
document.addEventListener("keyup", handler); // מקש שוחרר
document.addEventListener("keypress", handler); // מקש נלחץ (deprecated)
אירועי טפסים
input.addEventListener("focus", handler); // קיבל פוקוס
input.addEventListener("blur", handler); // איבד פוקוס
input.addEventListener("input", handler); // ערך השתנה
input.addEventListener("change", handler); // ערך השתנה (סיום)
form.addEventListener("submit", handler); // טופס נשלח
אירועי דף
window.addEventListener("load", handler); // הדף נטען
document.addEventListener("DOMContentLoaded", handler); // DOM מוכן
window.addEventListener("resize", handler); // גודל השתנה
window.addEventListener("scroll", handler); // גלילה
Event Object
כל handler מקבל אובייקט event עם מידע על האירוע:
button.addEventListener("click", function(event) {
console.log(event.type); // "click"
console.log(event.target); // האלמנט שנלחץ
console.log(event.currentTarget); // האלמנט עם הlistener
});
// קיצור נפוץ
button.addEventListener("click", (e) => {
console.log(e.target);
});
מידע על עכבר
element.addEventListener("click", (e) => {
console.log(e.clientX, e.clientY); // מיקום בחלון
console.log(e.pageX, e.pageY); // מיקום בדף
console.log(e.button); // איזה כפתור (0=שמאל)
});
מידע על מקלדת
document.addEventListener("keydown", (e) => {
console.log(e.key); // "Enter", "a", "ArrowUp"
console.log(e.code); // "Enter", "KeyA", "ArrowUp"
console.log(e.shiftKey); // האם Shift לחוץ
console.log(e.ctrlKey); // האם Ctrl לחוץ
console.log(e.altKey); // האם Alt לחוץ
if (e.key === "Enter") {
console.log("לחצת Enter!");
}
});
preventDefault - מניעת ברירת מחדל
// מניעת שליחת טופס
form.addEventListener("submit", (e) => {
e.preventDefault(); // הדף לא יתרענן
console.log("הטופס נקלט!");
// עיבוד הנתונים...
});
// מניעת פתיחת קישור
link.addEventListener("click", (e) => {
e.preventDefault();
console.log("מנעתי מעבר לקישור");
});
stopPropagation - עצירת התפשטות
אירועים "מבעבעים" למעלה בעץ ה-DOM:
/*
<div id="outer">
<div id="inner">
<button id="btn">לחץ</button>
</div>
</div>
*/
const outer = document.querySelector("#outer");
const inner = document.querySelector("#inner");
const btn = document.querySelector("#btn");
outer.addEventListener("click", () => console.log("outer"));
inner.addEventListener("click", () => console.log("inner"));
btn.addEventListener("click", (e) => {
console.log("button");
e.stopPropagation(); // עוצר את ההתפשטות
});
// לחיצה על הכפתור תדפיס רק "button"
// בלי stopPropagation היה מדפיס: "button", "inner", "outer"
Event Delegation
טכניקה יעילה - הוספת listener אחד להורה במקום לכל ילד:
/*
<ul id="list">
<li>פריט 1</li>
<li>פריט 2</li>
<li>פריט 3</li>
</ul>
*/
const list = document.querySelector("#list");
// ❌ לא יעיל - listener לכל li
document.querySelectorAll("li").forEach(li => {
li.addEventListener("click", () => {
console.log(li.textContent);
});
});
// ✅ יעיל - listener אחד על הרשימה
list.addEventListener("click", (e) => {
if (e.target.tagName === "LI") {
console.log(e.target.textContent);
}
});
// יתרון: עובד גם על פריטים שיתווספו בעתיד!
הסרת Event Listener
function handleClick() {
console.log("לחצת!");
}
// הוספה
button.addEventListener("click", handleClick);
// הסרה
button.removeEventListener("click", handleClick);
// ❌ לא עובד עם פונקציה אנונימית
button.addEventListener("click", () => console.log("שלום"));
button.removeEventListener("click", () => console.log("שלום")); // לא אותה פונקציה!
once - הרצה פעם אחת
button.addEventListener("click", () => {
console.log("זה יקרה רק פעם אחת!");
}, { once: true });
דוגמאות מעשיות
Toggle Button
const toggleBtn = document.querySelector("#toggle");
const content = document.querySelector("#content");
toggleBtn.addEventListener("click", () => {
content.classList.toggle("hidden");
toggleBtn.textContent = content.classList.contains("hidden")
? "הצג"
: "הסתר";
});
Form Validation
const form = document.querySelector("#form");
const emailInput = document.querySelector("#email");
const errorMsg = document.querySelector("#error");
form.addEventListener("submit", (e) => {
e.preventDefault();
const email = emailInput.value;
if (!email.includes("@")) {
errorMsg.textContent = "אימייל לא תקין";
emailInput.classList.add("invalid");
} else {
errorMsg.textContent = "";
emailInput.classList.remove("invalid");
console.log("הטופס נשלח!");
}
});
Character Counter
const textarea = document.querySelector("#message");
const counter = document.querySelector("#counter");
const maxLength = 100;
textarea.addEventListener("input", () => {
const remaining = maxLength - textarea.value.length;
counter.textContent = `נותרו ${remaining} תווים`;
if (remaining < 10) {
counter.style.color = "red";
} else {
counter.style.color = "black";
}
});
Keyboard Shortcuts
document.addEventListener("keydown", (e) => {
// Ctrl+S
if (e.ctrlKey && e.key === "s") {
e.preventDefault();
console.log("שומר...");
}
// Escape
if (e.key === "Escape") {
console.log("סוגר...");
}
});
Drag & Drop (בסיסי)
const draggable = document.querySelector("#draggable");
const dropzone = document.querySelector("#dropzone");
draggable.addEventListener("dragstart", (e) => {
e.dataTransfer.setData("text/plain", draggable.id);
});
dropzone.addEventListener("dragover", (e) => {
e.preventDefault(); // מאפשר drop
});
dropzone.addEventListener("drop", (e) => {
e.preventDefault();
const id = e.dataTransfer.getData("text/plain");
const element = document.getElementById(id);
dropzone.appendChild(element);
});
דוגמה מלאה - Todo List
HTML
<div id="app">
<h1>רשימת משימות</h1>
<form id="todoForm">
<input type="text" id="todoInput" placeholder="משימה חדשה...">
<button type="submit">הוסף</button>
</form>
<ul id="todoList"></ul>
</div>
JavaScript
const form = document.querySelector("#todoForm");
const input = document.querySelector("#todoInput");
const list = document.querySelector("#todoList");
// הוספת משימה
form.addEventListener("submit", (e) => {
e.preventDefault();
const text = input.value.trim();
if (!text) return;
const li = document.createElement("li");
li.innerHTML = `
<span>${text}</span>
<button class="delete">מחק</button>
`;
list.appendChild(li);
input.value = "";
input.focus();
});
// מחיקה והשלמה (delegation)
list.addEventListener("click", (e) => {
const li = e.target.closest("li");
if (e.target.classList.contains("delete")) {
li.remove();
} else if (e.target.tagName === "SPAN") {
li.classList.toggle("completed");
}
});
סיכום
| אירוע | מתי קורה |
|---|---|
click |
לחיצת עכבר |
dblclick |
לחיצה כפולה |
keydown |
מקש נלחץ |
keyup |
מקש שוחרר |
submit |
טופס נשלח |
input |
ערך השתנה |
focus |
אלמנט קיבל פוקוס |
blur |
אלמנט איבד פוקוס |
mouseenter |
עכבר נכנס |
mouseleave |
עכבר יצא |
load |
הדף נטען |
scroll |
גלילה |
כללי אצבע:
- השתמשו ב-addEventListener
- השתמשו ב-Event Delegation לביצועים טובים
- השתמשו ב-preventDefault() לשלוט בהתנהגות
- זכרו שאירועים "מבעבעים" למעלה
תכנות אסינכרוני (Asynchronous Programming)
JavaScript היא שפה single-threaded, אבל יכולה לבצע פעולות ברקע בזכות מנגנון האסינכרוניות.
למה צריך קוד אסינכרוני?
פעולות מסוימות לוקחות זמן: - קריאות לשרת (API) - קריאת קבצים - טיימרים - אנימציות
בלי אסינכרוניות, הדף היה "נתקע" עד שהפעולה מסתיימת.
// ❌ קוד סינכרוני שנתקע
console.log("התחלה");
// ...המתנה של 3 שניות...
console.log("סוף");
// ✅ קוד אסינכרוני - הדף ממשיך לעבוד
console.log("התחלה");
setTimeout(() => {
console.log("אחרי 3 שניות");
}, 3000);
console.log("ממשיך מיד");
setTimeout ו-setInterval
setTimeout - הרצה אחרי זמן
console.log("התחלה");
setTimeout(() => {
console.log("עברו 2 שניות");
}, 2000); // 2000 מילישניות = 2 שניות
console.log("ממשיך");
// פלט: "התחלה", "ממשיך", "עברו 2 שניות"
ביטול setTimeout
const timerId = setTimeout(() => {
console.log("זה לא ירוץ");
}, 5000);
// ביטול
clearTimeout(timerId);
setInterval - הרצה חוזרת
let count = 0;
const intervalId = setInterval(() => {
count++;
console.log(`פעם ${count}`);
if (count >= 5) {
clearInterval(intervalId); // עצירה
}
}, 1000); // כל שנייה
Callbacks
Callback היא פונקציה שמועברת כפרמטר ותקרא כשהפעולה מסתיימת:
function fetchData(callback) {
setTimeout(() => {
const data = { name: "דן", age: 25 };
callback(data); // קריאה ל-callback עם הנתונים
}, 2000);
}
fetchData((result) => {
console.log("קיבלתי:", result);
});
Callback Hell (הבעיה)
// ❌ קשה לקריאה ותחזוקה
getData((data) => {
processData(data, (processed) => {
saveData(processed, (saved) => {
notifyUser(saved, (notification) => {
console.log("סיום!");
});
});
});
});
Promises
Promise הוא אובייקט שמייצג ערך עתידי - הוא יכול להצליח (resolve) או להיכשל (reject).
יצירת Promise
const myPromise = new Promise((resolve, reject) => {
// פעולה אסינכרונית
setTimeout(() => {
const success = true;
if (success) {
resolve("הצלחה!"); // מחזיר ערך
} else {
reject("נכשל!"); // מחזיר שגיאה
}
}, 2000);
});
שימוש ב-Promise
myPromise
.then((result) => {
console.log("הצלחה:", result);
})
.catch((error) => {
console.log("שגיאה:", error);
})
.finally(() => {
console.log("תמיד רץ - הצלחה או כישלון");
});
שרשור Promises
fetchUser(userId)
.then((user) => {
console.log("משתמש:", user.name);
return fetchPosts(user.id);
})
.then((posts) => {
console.log("פוסטים:", posts.length);
return fetchComments(posts[0].id);
})
.then((comments) => {
console.log("תגובות:", comments.length);
})
.catch((error) => {
console.error("שגיאה בשרשרת:", error);
});
async/await
תחביר מודרני ונקי יותר לעבודה עם Promises:
פונקציה async
async function getData() {
return "נתונים"; // מחזיר Promise אוטומטית
}
getData().then(result => console.log(result)); // "נתונים"
await - המתנה ל-Promise
async function fetchData() {
console.log("מתחיל...");
const response = await fetch("https://api.example.com/data");
const data = await response.json();
console.log("קיבלתי:", data);
return data;
}
fetchData();
טיפול בשגיאות
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error("שגיאה:", error.message);
return null;
}
}
השוואה: Promises vs async/await
// עם Promises
function getUser() {
return fetch("/api/user")
.then(response => response.json())
.then(user => {
console.log(user);
return user;
})
.catch(error => console.error(error));
}
// עם async/await (נקי יותר)
async function getUser() {
try {
const response = await fetch("/api/user");
const user = await response.json();
console.log(user);
return user;
} catch (error) {
console.error(error);
}
}
Promise.all
הרצת מספר Promises במקביל:
async function fetchAllData() {
try {
// כל הבקשות יוצאות במקביל
const [users, posts, comments] = await Promise.all([
fetch("/api/users").then(r => r.json()),
fetch("/api/posts").then(r => r.json()),
fetch("/api/comments").then(r => r.json())
]);
console.log("משתמשים:", users.length);
console.log("פוסטים:", posts.length);
console.log("תגובות:", comments.length);
} catch (error) {
// אם אחת נכשלת - הכל נכשל
console.error("שגיאה:", error);
}
}
Promise.race
מחזיר את התוצאה הראשונה (הצלחה או כישלון):
async function fetchWithTimeout(url, timeout = 5000) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error("Timeout!")), timeout);
});
const fetchPromise = fetch(url);
return Promise.race([fetchPromise, timeoutPromise]);
}
Promise.allSettled
ממתין לכולם, גם אם חלק נכשלים:
const promises = [
fetch("/api/users"),
fetch("/api/posts"),
fetch("/api/bad-url") // יכשל
];
const results = await Promise.allSettled(promises);
results.forEach((result, index) => {
if (result.status === "fulfilled") {
console.log(`#${index} הצליח:`, result.value);
} else {
console.log(`#${index} נכשל:`, result.reason);
}
});
דוגמאות מעשיות
טעינת נתונים עם Loading
async function loadUsers() {
const loadingEl = document.querySelector("#loading");
const listEl = document.querySelector("#userList");
loadingEl.style.display = "block";
try {
const response = await fetch("/api/users");
const users = await response.json();
listEl.innerHTML = users
.map(user => `<li>${user.name}</li>`)
.join("");
} catch (error) {
listEl.innerHTML = "<li>שגיאה בטעינה</li>";
} finally {
loadingEl.style.display = "none";
}
}
Debounce - עיכוב הרצה
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
// שימוש - חיפוש שמחכה שהמשתמש יפסיק להקליד
const searchInput = document.querySelector("#search");
const search = debounce((query) => {
console.log("מחפש:", query);
// קריאה לAPI
}, 300);
searchInput.addEventListener("input", (e) => {
search(e.target.value);
});
Retry - ניסיון חוזר
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url);
if (response.ok) {
return await response.json();
}
} catch (error) {
console.log(`ניסיון ${i + 1} נכשל`);
if (i === retries - 1) {
throw error;
}
// המתנה לפני ניסיון נוסף
await new Promise(r => setTimeout(r, 1000));
}
}
}
Event Loop (איך זה עובד)
┌───────────────────────────┐
│ Call Stack │ ← JavaScript רץ כאן
└───────────────────────────┘
↓
┌───────────────────────────┐
│ Web APIs │ ← setTimeout, fetch, etc.
│ (מנוהל ע"י הדפדפן) │
└───────────────────────────┘
↓
┌───────────────────────────┐
│ Callback Queue │ ← callbacks ממתינים
└───────────────────────────┘
↓
┌───────────────────────────┐
│ Event Loop │ ← מעביר לStack כשפנוי
└───────────────────────────┘
console.log("1");
setTimeout(() => {
console.log("2");
}, 0);
Promise.resolve().then(() => {
console.log("3");
});
console.log("4");
// פלט: 1, 4, 3, 2
// (Microtasks/Promises קודמים ל-setTimeout)
סיכום
| מושג | תיאור |
|---|---|
| Callback | פונקציה שתקרא בסיום פעולה |
| Promise | אובייקט שמייצג ערך עתידי |
| async | מגדיר פונקציה אסינכרונית |
| await | ממתין ל-Promise |
| try/catch | טיפול בשגיאות |
| Promise.all | הרצה במקביל, כולם חייבים להצליח |
| Promise.race | הראשון שמסתיים |
| Promise.allSettled | כולם, גם עם כישלונות |
כללי אצבע:
- העדיפו async/await על פני .then()
- תמיד טפלו בשגיאות עם try/catch
- השתמשו ב-Promise.all לבקשות מקביליות
- הימנעו מ-callback hell
קריאות שרת (Fetch API)
Fetch API מאפשרת לתקשר עם שרתים - לקבל ולשלוח נתונים דרך HTTP.
מה זה API?
API (Application Programming Interface) הוא ממשק שמאפשר לתוכנות לתקשר זו עם זו. בהקשר של ווב, מדובר בנקודות קצה (endpoints) בשרת שאפשר לפנות אליהן.
┌─────────────────┐ HTTP Request ┌─────────────────┐
│ │ ──────────────▶ │ │
│ Frontend │ │ Backend │
│ (JavaScript) │ ◀────────────── │ (Server) │
│ │ HTTP Response │ │
└─────────────────┘ └─────────────────┘
HTTP Methods (שיטות)
| Method | שימוש | דוגמה |
|---|---|---|
| GET | קבלת נתונים | לקבל רשימת משתמשים |
| POST | יצירת נתון חדש | יצירת משתמש חדש |
| PUT | עדכון כל הנתון | עדכון כל פרטי המשתמש |
| PATCH | עדכון חלקי | עדכון שם בלבד |
| DELETE | מחיקה | מחיקת משתמש |
fetch בסיסי (GET)
// בקשת GET פשוטה
fetch("https://jsonplaceholder.typicode.com/users")
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.error("שגיאה:", error);
});
עם async/await
async function getUsers() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await response.json();
console.log(users);
} catch (error) {
console.error("שגיאה:", error);
}
}
getUsers();
Response Object
האובייקט שחוזר מ-fetch מכיל מידע על התשובה:
async function checkResponse() {
const response = await fetch("/api/users");
console.log(response.status); // 200, 404, 500...
console.log(response.ok); // true אם status 200-299
console.log(response.statusText); // "OK", "Not Found"...
console.log(response.headers); // Headers object
// קריאת הגוף (אפשר רק פעם אחת!)
const data = await response.json();
}
בדיקת תקינות התשובה
async function fetchData(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
שליחת נתונים (POST)
async function createUser(user) {
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(user)
});
const newUser = await response.json();
return newUser;
}
// שימוש
const user = await createUser({
name: "דן",
email: "[email protected]"
});
console.log("נוצר:", user);
עדכון נתונים (PUT/PATCH)
PUT - החלפה מלאה
async function updateUser(id, userData) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(userData)
});
return response.json();
}
PATCH - עדכון חלקי
async function updateUserEmail(id, email) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ email })
});
return response.json();
}
מחיקה (DELETE)
async function deleteUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: "DELETE"
});
if (response.ok) {
console.log("המשתמש נמחק");
}
}
Headers
async function fetchWithAuth() {
const response = await fetch("/api/protected-data", {
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_TOKEN_HERE",
"Accept-Language": "he"
}
});
return response.json();
}
טיפול בשגיאות
async function fetchWithErrorHandling(url) {
try {
const response = await fetch(url);
// בדיקת סטטוס
if (!response.ok) {
if (response.status === 404) {
throw new Error("לא נמצא");
} else if (response.status === 401) {
throw new Error("לא מורשה");
} else if (response.status >= 500) {
throw new Error("שגיאת שרת");
} else {
throw new Error(`שגיאה: ${response.status}`);
}
}
return await response.json();
} catch (error) {
// שגיאת רשת (אין חיבור)
if (error.name === "TypeError") {
console.error("בעיית חיבור לרשת");
} else {
console.error(error.message);
}
throw error;
}
}
Query Parameters
// דרך 1: ידנית
const url = "https://api.example.com/users?page=1&limit=10";
// דרך 2: URLSearchParams
const params = new URLSearchParams({
page: 1,
limit: 10,
sort: "name"
});
const url2 = `https://api.example.com/users?${params}`;
// "https://api.example.com/users?page=1&limit=10&sort=name"
// דרך 3: URL object
const url3 = new URL("https://api.example.com/users");
url3.searchParams.append("page", 1);
url3.searchParams.append("limit", 10);
AbortController - ביטול בקשה
const controller = new AbortController();
// ביטול אחרי 5 שניות
setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch("/api/data", {
signal: controller.signal
});
const data = await response.json();
} catch (error) {
if (error.name === "AbortError") {
console.log("הבקשה בוטלה");
} else {
console.error("שגיאה:", error);
}
}
FormData - שליחת טפסים
// מטופס קיים
const form = document.querySelector("#myForm");
const formData = new FormData(form);
await fetch("/api/submit", {
method: "POST",
body: formData // לא צריך Content-Type header!
});
// ידנית
const data = new FormData();
data.append("name", "דן");
data.append("file", fileInput.files[0]);
await fetch("/api/upload", {
method: "POST",
body: data
});
דוגמה מלאה - CRUD Application
const API_URL = "https://jsonplaceholder.typicode.com";
// READ - קבלת כל המשתמשים
async function getUsers() {
const response = await fetch(`${API_URL}/users`);
return response.json();
}
// READ - קבלת משתמש ספציפי
async function getUser(id) {
const response = await fetch(`${API_URL}/users/${id}`);
if (!response.ok) throw new Error("משתמש לא נמצא");
return response.json();
}
// CREATE - יצירת משתמש
async function createUser(userData) {
const response = await fetch(`${API_URL}/users`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(userData)
});
return response.json();
}
// UPDATE - עדכון משתמש
async function updateUser(id, userData) {
const response = await fetch(`${API_URL}/users/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(userData)
});
return response.json();
}
// DELETE - מחיקת משתמש
async function deleteUser(id) {
const response = await fetch(`${API_URL}/users/${id}`, {
method: "DELETE"
});
return response.ok;
}
// שימוש
async function main() {
try {
// קבלת כל המשתמשים
const users = await getUsers();
console.log("משתמשים:", users.length);
// קבלת משתמש ספציפי
const user = await getUser(1);
console.log("משתמש:", user.name);
// יצירה
const newUser = await createUser({
name: "דן ישראלי",
email: "[email protected]"
});
console.log("נוצר:", newUser);
} catch (error) {
console.error("שגיאה:", error.message);
}
}
main();
טעינת נתונים עם UI
async function loadUsersToPage() {
const container = document.querySelector("#users");
const loading = document.querySelector("#loading");
const error = document.querySelector("#error");
// הצגת טעינה
loading.style.display = "block";
error.style.display = "none";
container.innerHTML = "";
try {
const response = await fetch("/api/users");
if (!response.ok) {
throw new Error("שגיאה בטעינת המשתמשים");
}
const users = await response.json();
// בניית ה-HTML
container.innerHTML = users.map(user => `
<div class="user-card">
<h3>${user.name}</h3>
<p>${user.email}</p>
</div>
`).join("");
} catch (err) {
error.textContent = err.message;
error.style.display = "block";
} finally {
loading.style.display = "none";
}
}
// טעינה בעליית הדף
document.addEventListener("DOMContentLoaded", loadUsersToPage);
JSON
עבודה עם JSON
// המרה למחרוזת JSON
const obj = { name: "דן", age: 25 };
const jsonString = JSON.stringify(obj);
console.log(jsonString); // '{"name":"דן","age":25}'
// המרה מ-JSON לאובייקט
const parsed = JSON.parse(jsonString);
console.log(parsed.name); // "דן"
// JSON יפה (לקריאה)
const pretty = JSON.stringify(obj, null, 2);
XMLHttpRequest (לידע כללי)
הדרך הישנה לבקשות HTTP (לפני fetch):
// ❌ הדרך הישנה
const xhr = new XMLHttpRequest();
xhr.open("GET", "/api/users");
xhr.onload = function() {
if (xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
console.log(data);
}
};
xhr.onerror = function() {
console.error("שגיאה");
};
xhr.send();
// ✅ fetch מודרני
const response = await fetch("/api/users");
const data = await response.json();
סיכום
| פעולה | קוד |
|---|---|
| GET | fetch(url) |
| POST | fetch(url, { method: "POST", body: ... }) |
| PUT | fetch(url, { method: "PUT", body: ... }) |
| DELETE | fetch(url, { method: "DELETE" }) |
| קריאת JSON | response.json() |
| בדיקת תקינות | response.ok או response.status |
| שליחת JSON | body: JSON.stringify(data) |
| Headers | headers: { "Content-Type": "application/json" } |
כללי אצבע:
- תמיד בדקו response.ok לפני עיבוד התשובה
- השתמשו ב-try/catch לטיפול בשגיאות
- השתמשו ב-async/await לקוד נקי
- אל תשכחו את Content-Type header בשליחת JSON
שיטות עבודה מומלצות (Best Practices)
אוסף של טיפים וכללים לכתיבת קוד JavaScript נקי, קריא ותחזיקתי.
מוסכמות שמות (Naming Conventions)
משתנים ופונקציות - camelCase
// ✅ טוב
let userName = "דן";
let totalAmount = 100;
function calculateTotal() { }
function getUserData() { }
// ❌ לא מומלץ
let user_name = "דן";
let TOTALAMOUNT = 100;
קבועים - SCREAMING_SNAKE_CASE
const MAX_USERS = 100;
const API_BASE_URL = "https://api.example.com";
const DEFAULT_TIMEOUT = 5000;
Classes ו-Constructors - PascalCase
class UserProfile { }
class ShoppingCart { }
function Person(name) {
this.name = name;
}
Boolean - שאלות
// ✅ ברור שזה boolean
let isActive = true;
let hasPermission = false;
let canEdit = true;
let shouldUpdate = false;
// ❌ לא ברור
let active = true;
let permission = false;
כתיבת פונקציות
פונקציה צריכה לעשות דבר אחד
// ❌ פונקציה שעושה יותר מדי
function processUser(user) {
// אימות
// עדכון DB
// שליחת אימייל
// עדכון לוג
}
// ✅ פונקציות קטנות וממוקדות
function validateUser(user) { }
function saveUser(user) { }
function sendWelcomeEmail(user) { }
function logUserCreation(user) { }
שמות תיאוריים
// ❌ לא ברור
function process(d) { }
function doStuff(x, y) { }
// ✅ ברור מה הפונקציה עושה
function calculateTotalPrice(items) { }
function formatDateForDisplay(date) { }
function validateEmailAddress(email) { }
ערכי ברירת מחדל
// ✅ ברירות מחדל מונעות undefined
function createUser(name, role = "user", active = true) {
return { name, role, active };
}
// ✅ עם destructuring
function greet({ name = "אורח", greeting = "שלום" } = {}) {
return `${greeting} ${name}!`;
}
עבודה עם משתנים
const כברירת מחדל
// ✅ השתמשו ב-const אם הערך לא משתנה
const API_URL = "https://api.example.com";
const config = { debug: true };
// השתמשו ב-let רק כשצריך לשנות
let count = 0;
count++;
הימנעו מ-var
// ❌ var - בעיות scope
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// ידפיס: 3, 3, 3
// ✅ let - מתנהג כמצופה
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// ידפיס: 0, 1, 2
Destructuring
// ❌ ארוך
const name = user.name;
const age = user.age;
const city = user.address.city;
// ✅ קצר וקריא
const { name, age, address: { city } } = user;
// עם מערכים
const [first, second, ...rest] = items;
השוואות ותנאים
השתמשו ב-=== ו-!==
// ❌ השוואה רופפת
if (value == "5") { }
// ✅ השוואה מדויקת
if (value === "5") { }
if (value === 5) { }
התנאים הקצרים
// ❌ מסורבל
if (array.length > 0) {
return true;
} else {
return false;
}
// ✅ פשוט
return array.length > 0;
// Optional chaining
const city = user?.address?.city;
// Nullish coalescing
const name = user.name ?? "אנונימי";
Early Return
// ❌ קשה לקריאה
function processUser(user) {
if (user) {
if (user.active) {
if (user.role === "admin") {
// הרבה קוד
}
}
}
}
// ✅ קל לקריאה
function processUser(user) {
if (!user) return;
if (!user.active) return;
if (user.role !== "admin") return;
// הקוד הראשי
}
עבודה עם מערכים
שימוש במתודות פונקציונליות
// ❌ לולאה מסורבלת
const doubled = [];
for (let i = 0; i < numbers.length; i++) {
doubled.push(numbers[i] * 2);
}
// ✅ קצר וקריא
const doubled = numbers.map(n => n * 2);
// סינון
const adults = users.filter(u => u.age >= 18);
// מציאה
const admin = users.find(u => u.role === "admin");
// בדיקה
const hasAdmin = users.some(u => u.role === "admin");
Spread ו-Destructuring
// ✅ העתקה
const copy = [...originalArray];
const merged = [...array1, ...array2];
// הוספה לתחילה/סוף
const withFirst = [newItem, ...array];
const withLast = [...array, newItem];
עבודה עם אובייקטים
Spread לעדכון
// ✅ עדכון אימטבילי
const updatedUser = {
...user,
name: "שם חדש",
age: user.age + 1
};
// מיזוג
const merged = { ...defaults, ...userSettings };
Shorthand Properties
const name = "דן";
const age = 25;
// ❌ חזרה
const user = { name: name, age: age };
// ✅ קיצור
const user = { name, age };
טיפול בשגיאות
תמיד תפסו שגיאות בקוד אסינכרוני
// ✅ try/catch עם async
async function fetchData() {
try {
const response = await fetch("/api/data");
return await response.json();
} catch (error) {
console.error("שגיאה:", error);
return null;
}
}
// ✅ .catch עם promises
fetch("/api/data")
.then(res => res.json())
.catch(error => {
console.error("שגיאה:", error);
});
שגיאות ספציפיות
// ✅ מידע ברור בשגיאה
throw new Error(`משתמש ${userId} לא נמצא`);
// ✅ בדיקות מפורטות
if (!response.ok) {
if (response.status === 404) {
throw new Error("לא נמצא");
} else if (response.status === 401) {
throw new Error("לא מורשה");
}
throw new Error(`שגיאה: ${response.status}`);
}
הערות ותיעוד
הערות שמסבירות למה, לא מה
// ❌ מה - מובן מהקוד
// מגדיל את count ב-1
count++;
// ✅ למה - לא מובן מהקוד
// מוסיף 1 כי ה-API מחזיר 0-indexed
displayedPage = apiPage + 1;
// ✅ הסבר של לוגיקה מורכבת
// משתמשים ב-debounce כי ה-API מגביל ל-100 בקשות בדקה
const debouncedSearch = debounce(search, 300);
JSDoc לפונקציות מורכבות
/**
* מחשב את המחיר הכולל כולל הנחה
* @param {number} price - מחיר הבסיס
* @param {number} quantity - כמות
* @param {number} [discount=0] - אחוז הנחה (אופציונלי)
* @returns {number} המחיר הסופי
*/
function calculateTotal(price, quantity, discount = 0) {
const subtotal = price * quantity;
return subtotal - (subtotal * discount / 100);
}
Debugging
console מתקדם
// טבלה
console.table([{ name: "דן", age: 25 }, { name: "דנה", age: 30 }]);
// קיבוץ
console.group("פרטי משתמש");
console.log("שם:", user.name);
console.log("גיל:", user.age);
console.groupEnd();
// זמן ביצוע
console.time("פעולה");
// ... קוד ...
console.timeEnd("פעולה");
// תנאי
console.assert(value > 0, "הערך חייב להיות חיובי");
Breakpoints
// עצירה בקוד
debugger;
// או בDevTools - לחיצה על מספר השורה
ביצועים
הימנעו מפעולות DOM מיותרות
// ❌ עדכון DOM בכל איטרציה
for (let item of items) {
container.innerHTML += `<div>${item}</div>`;
}
// ✅ בניית HTML ועדכון אחד
const html = items.map(item => `<div>${item}</div>`).join("");
container.innerHTML = html;
Debounce ו-Throttle
// Debounce - ממתין שהמשתמש יפסיק להקליד
const debouncedSearch = debounce(search, 300);
input.addEventListener("input", debouncedSearch);
// Throttle - מבצע מקסימום פעם ב-X זמן
const throttledScroll = throttle(handleScroll, 100);
window.addEventListener("scroll", throttledScroll);
אבטחה
הימנעו מ-innerHTML עם קלט משתמש
// ❌ מסוכן - XSS
element.innerHTML = userInput;
// ✅ בטוח
element.textContent = userInput;
// ✅ אם חייבים HTML - נקו קודם
element.innerHTML = DOMPurify.sanitize(userInput);
אל תשמרו מידע רגיש ב-Client
// ❌ לעולם לא!
const PRIVATE_KEY = "secret123";
localStorage.setItem("password", password);
// ✅ רק בשרת
// הטוקנים נשמרים בצורה מאובטחת (httpOnly cookies)
סיכום
| נושא | כלל |
|---|---|
| משתנים | const כברירת מחדל |
| השוואות | תמיד === |
| פונקציות | קטנות וממוקדות |
| שגיאות | תמיד try/catch באסינכרוני |
| מערכים | map, filter, find |
| DOM | מינימום עדכונים |
| אבטחה | textContent ולא innerHTML |
עקרונות כלליים: - קוד קריא עדיף על קוד "חכם" - DRY - Don't Repeat Yourself - KISS - Keep It Simple, Stupid - עדכנו קוד ישן כשנוגעים בו - כתבו קוד שאתם תרצו לתחזק בעוד שנה
ביטויים רגולריים (Regular Expressions)
מה זה Regex?
ביטויים רגולריים (Regular Expressions או בקיצור Regex) הם תבניות המשמשות לחיפוש, התאמה ומניפולציה של טקסט. הם כלי רב-עוצמה לעבודה עם מחרוזות.
┌─────────────────────────────────────────────────┐
│ Regex │
│ ┌──────────────┐ ┌──────────────────────┐ │
│ │ תבנית חיפוש │ → │ התאמה במחרוזת │ │
│ │ /hello/ │ │ "hello world" │ │
│ └──────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────┘
יצירת Regex ב-JavaScript
שתי דרכים ליצירת Regex
// 1. Literal notation - הדרך הנפוצה
const regex1 = /hello/;
// 2. Constructor - שימושי כשהתבנית דינמית
const regex2 = new RegExp('hello');
// עם דגלים (flags)
const regex3 = /hello/gi;
const regex4 = new RegExp('hello', 'gi');
דגלים (Flags)
דגלים משנים את התנהגות החיפוש:
| דגל | שם | משמעות |
|---|---|---|
g |
global | מצא את כל ההתאמות, לא רק הראשונה |
i |
case-insensitive | התעלם מהבדלי אותיות גדולות/קטנות |
m |
multiline | התייחס לכל שורה כמחרוזת נפרדת |
s |
dotAll | נקודה תתאים גם לשורה חדשה |
u |
unicode | תמיכה מלאה ב-Unicode |
// חיפוש ללא רגישות לאותיות
const regex = /hello/i;
console.log(regex.test('HELLO')); // true
console.log(regex.test('Hello')); // true
// מציאת כל ההתאמות
const str = 'cat cat cat';
const matches = str.match(/cat/g);
console.log(matches); // ['cat', 'cat', 'cat']
תווים מיוחדים
Meta Characters - תווי מטא
| תו | משמעות | דוגמה |
|---|---|---|
. |
כל תו בודד (חוץ משורה חדשה) | a.c מתאים ל-abc, aXc |
\d |
ספרה (0-9) | \d\d מתאים ל-42 |
\D |
לא ספרה | \D מתאים ל-a, ! |
\w |
תו מילה (a-z, A-Z, 0-9, _) | \w+ מתאים ל-hello_123 |
\W |
לא תו מילה | \W מתאים ל-@, |
\s |
רווח לבן (space, tab, newline) | \s+ מתאים לרווחים |
\S |
לא רווח לבן | \S+ מתאים למילה |
\b |
גבול מילה | \bcat\b מתאים ל-cat אך לא ל-category |
\n |
שורה חדשה | |
\t |
טאב |
// חיפוש ספרות
const phone = '054-1234567';
console.log(phone.match(/\d+/g)); // ['054', '1234567']
// חיפוש מילים
const text = 'Hello World 123';
console.log(text.match(/\w+/g)); // ['Hello', 'World', '123']
כימות (Quantifiers)
כמה פעמים התו יופיע
| כימות | משמעות | דוגמה |
|---|---|---|
* |
0 או יותר | ab*c → ac, abc, abbc |
+ |
1 או יותר | ab+c → abc, abbc (לא ac) |
? |
0 או 1 | colou?r → color, colour |
{n} |
בדיוק n פעמים | a{3} → aaa |
{n,} |
n או יותר | a{2,} → aa, aaa, aaaa... |
{n,m} |
בין n ל-m פעמים | a{2,4} → aa, aaa, aaaa |
// מספר טלפון ישראלי
const phoneRegex = /^0\d{1,2}-?\d{7}$/;
console.log(phoneRegex.test('054-1234567')); // true
console.log(phoneRegex.test('02-1234567')); // true
console.log(phoneRegex.test('0541234567')); // true
// כתובת דוא"ל פשוטה
const emailRegex = /\w+@\w+\.\w+/;
console.log(emailRegex.test('[email protected]')); // true
קבוצות וטווחים
Character Classes - מחלקות תווים
// טווח של אותיות
const regex1 = /[a-z]/; // אות קטנה אחת
const regex2 = /[A-Z]/; // אות גדולה אחת
const regex3 = /[0-9]/; // ספרה (כמו \d)
const regex4 = /[a-zA-Z]/; // כל אות
// תווים ספציפיים
const vowels = /[aeiou]/gi;
const text = 'Hello World';
console.log(text.match(vowels)); // ['e', 'o', 'o']
// שלילה עם ^
const notDigit = /[^0-9]/; // כל תו שהוא לא ספרה
console.log('a1b2'.match(/[^0-9]/g)); // ['a', 'b']
Groups - קבוצות
// קבוצות לכידה (Capturing Groups)
const regex = /(\d{2})-(\d{2})-(\d{4})/;
const date = '25-12-2024';
const match = date.match(regex);
console.log(match[0]); // '25-12-2024' (כל ההתאמה)
console.log(match[1]); // '25' (קבוצה ראשונה)
console.log(match[2]); // '12' (קבוצה שנייה)
console.log(match[3]); // '2024' (קבוצה שלישית)
// קבוצות עם שמות (Named Groups)
const namedRegex = /(?<day>\d{2})-(?<month>\d{2})-(?<year>\d{4})/;
const namedMatch = date.match(namedRegex);
console.log(namedMatch.groups.day); // '25'
console.log(namedMatch.groups.month); // '12'
console.log(namedMatch.groups.year); // '2024'
עוגנים (Anchors)
עוגנים מציינים מיקום במחרוזת:
| עוגן | משמעות |
|---|---|
^ |
תחילת המחרוזת |
$ |
סוף המחרוזת |
\b |
גבול מילה |
\B |
לא גבול מילה |
// מתחיל עם "Hello"
const startsWithHello = /^Hello/;
console.log(startsWithHello.test('Hello World')); // true
console.log(startsWithHello.test('Say Hello')); // false
// מסתיים עם ספרות
const endsWithNumber = /\d+$/;
console.log(endsWithNumber.test('version 2')); // true
console.log(endsWithNumber.test('2 items')); // false
// מילה שלמה בלבד
const wholeWord = /\bcat\b/;
console.log(wholeWord.test('cat')); // true
console.log(wholeWord.test('category')); // false
console.log(wholeWord.test('a cat here')); // true
מתודות של Regex
test() - בדיקת התאמה
const regex = /hello/i;
// מחזיר true או false
console.log(regex.test('Hello World')); // true
console.log(regex.test('Goodbye')); // false
exec() - ביצוע חיפוש מפורט
const regex = /(\w+)@(\w+)\.(\w+)/;
const email = '[email protected]';
const result = regex.exec(email);
console.log(result[0]); // '[email protected]'
console.log(result[1]); // 'user'
console.log(result[2]); // 'example'
console.log(result[3]); // 'com'
console.log(result.index); // 0 (מיקום ההתאמה)
מתודות מחרוזת עם Regex
match() - מציאת התאמות
const text = 'The rain in Spain stays mainly in the plain';
// התאמה ראשונה בלבד
console.log(text.match(/ain/));
// ['ain', index: 5, input: '...']
// כל ההתאמות עם g flag
console.log(text.match(/ain/g));
// ['ain', 'ain', 'ain', 'ain']
matchAll() - כל ההתאמות עם פרטים
const text = 'cat bat rat';
const regex = /[cbr]at/g;
for (const match of text.matchAll(regex)) {
console.log(`נמצא: ${match[0]} במיקום ${match.index}`);
}
// נמצא: cat במיקום 0
// נמצא: bat במיקום 4
// נמצא: rat במיקום 8
replace() - החלפת טקסט
// החלפה פשוטה
const text = 'Hello World';
console.log(text.replace(/World/, 'JavaScript'));
// 'Hello JavaScript'
// החלפת כל ההתאמות
const text2 = 'cat cat cat';
console.log(text2.replace(/cat/g, 'dog'));
// 'dog dog dog'
// שימוש בקבוצות
const name = 'John Smith';
console.log(name.replace(/(\w+) (\w+)/, '$2, $1'));
// 'Smith, John'
// פונקציית החלפה
const prices = 'Items cost $5 and $10';
const converted = prices.replace(/\$(\d+)/g, (match, amount) => {
return `₪${amount * 3.5}`;
});
console.log(converted);
// 'Items cost ₪17.5 and ₪35'
replaceAll() - החלפת כל ההתאמות
const text = 'a-b-c-d';
console.log(text.replaceAll('-', '_'));
// 'a_b_c_d'
// עם regex (חייב דגל g)
console.log(text.replaceAll(/-/g, '_'));
// 'a_b_c_d'
search() - חיפוש אינדקס
const text = 'Hello World';
console.log(text.search(/World/)); // 6
console.log(text.search(/xyz/)); // -1 (לא נמצא)
split() - פיצול מחרוזת
// פיצול לפי תבנית
const text = 'apple, banana; cherry orange';
const fruits = text.split(/[,;\s]+/);
console.log(fruits);
// ['apple', 'banana', 'cherry', 'orange']
// פיצול עם שמירת המפריד
const text2 = 'one1two2three3';
const parts = text2.split(/(\d)/);
console.log(parts);
// ['one', '1', 'two', '2', 'three', '3', '']
דוגמאות שימושיות
ולידציה של נתונים
// ולידציית אימייל
function isValidEmail(email) {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
console.log(isValidEmail('[email protected]')); // true
console.log(isValidEmail('invalid.email')); // false
// ולידציית מספר טלפון ישראלי
function isValidPhoneIL(phone) {
const regex = /^0(5[0-9]|[2-4]|[7-9])\d{7}$/;
return regex.test(phone.replace(/-/g, ''));
}
console.log(isValidPhoneIL('054-1234567')); // true
console.log(isValidPhoneIL('02-1234567')); // true
// ולידציית סיסמה
function isStrongPassword(password) {
// לפחות 8 תווים, אות גדולה, אות קטנה, ספרה
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
return regex.test(password);
}
console.log(isStrongPassword('MyPass123')); // true
console.log(isStrongPassword('weak')); // false
// ולידציית ת.ז. ישראלית (9 ספרות)
function isValidIsraeliID(id) {
const regex = /^\d{9}$/;
return regex.test(id);
}
חילוץ מידע
// חילוץ כתובות URL
function extractURLs(text) {
const regex = /https?:\/\/[^\s]+/g;
return text.match(regex) || [];
}
const text = 'Visit https://example.com or http://test.org';
console.log(extractURLs(text));
// ['https://example.com', 'http://test.org']
// חילוץ האשטאגים
function extractHashtags(text) {
const regex = /#\w+/g;
return text.match(regex) || [];
}
const tweet = 'Love #JavaScript and #coding! #webdev';
console.log(extractHashtags(tweet));
// ['#JavaScript', '#coding', '#webdev']
// חילוץ מספרים
function extractNumbers(text) {
const regex = /-?\d+\.?\d*/g;
return text.match(regex)?.map(Number) || [];
}
console.log(extractNumbers('Price: 25.99, Discount: -5'));
// [25.99, -5]
ניקוי וטרנספורמציה
// הסרת HTML tags
function stripHTML(html) {
return html.replace(/<[^>]*>/g, '');
}
console.log(stripHTML('<p>Hello <b>World</b></p>'));
// 'Hello World'
// המרה ל-camelCase
function toCamelCase(str) {
return str.replace(/[-_\s]+(.)/g, (_, char) => char.toUpperCase());
}
console.log(toCamelCase('hello-world')); // 'helloWorld'
console.log(toCamelCase('my_variable_name')); // 'myVariableName'
// הוספת פסיקים למספרים גדולים
function formatNumber(num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
console.log(formatNumber(1234567)); // '1,234,567'
// ניקוי רווחים מיותרים
function cleanWhitespace(text) {
return text.replace(/\s+/g, ' ').trim();
}
console.log(cleanWhitespace(' Hello World '));
// 'Hello World'
Lookahead ו-Lookbehind
Lookahead - הסתכלות קדימה
// Positive Lookahead: (?=...)
// מצא "foo" שאחריו יש "bar"
const regex1 = /foo(?=bar)/;
console.log(regex1.test('foobar')); // true
console.log(regex1.test('foobaz')); // false
// Negative Lookahead: (?!...)
// מצא "foo" שאחריו אין "bar"
const regex2 = /foo(?!bar)/;
console.log(regex2.test('foobaz')); // true
console.log(regex2.test('foobar')); // false
Lookbehind - הסתכלות אחורה
// Positive Lookbehind: (?<=...)
// מצא מספר שלפניו יש $
const regex3 = /(?<=\$)\d+/;
console.log('$100'.match(regex3)); // ['100']
// Negative Lookbehind: (?<!...)
// מצא מספר שלפניו אין $
const regex4 = /(?<!\$)\d+/;
console.log('100'.match(regex4)); // ['100']
console.log('$100'.match(regex4)); // ['00'] (כי 1 בא אחרי $)
טעויות נפוצות
1. שכחת דגל g
// לא נכון - מחליף רק את הראשון
const text = 'cat cat cat';
console.log(text.replace(/cat/, 'dog')); // 'dog cat cat'
// נכון - מחליף את כולם
console.log(text.replace(/cat/g, 'dog')); // 'dog dog dog'
2. לא בריחה מתווים מיוחדים
// לא נכון - הנקודה זה wildcard
const regex1 = /example.com/;
console.log(regex1.test('exampleXcom')); // true (לא נכון!)
// נכון - בריחה עם \
const regex2 = /example\.com/;
console.log(regex2.test('exampleXcom')); // false
console.log(regex2.test('example.com')); // true
3. Greedy vs Lazy
// Greedy (ברירת מחדל) - לוקח הכי הרבה
const text = '<div>Hello</div><div>World</div>';
console.log(text.match(/<div>.*<\/div>/)[0]);
// '<div>Hello</div><div>World</div>' (הכל!)
// Lazy (עם ?) - לוקח הכי מעט
console.log(text.match(/<div>.*?<\/div>/)[0]);
// '<div>Hello</div>' (רק הראשון)
סיכום
- Regex הם כלי עוצמתי לעבודה עם טקסט
- דגלים כמו
g,i,mמשנים התנהגות - תווי מטא כמו
\d,\w,\sמייצגים קבוצות תווים - כימות כמו
*,+,{n,m}קובעים כמה פעמים - קבוצות
()מאפשרות לכידה והתייחסות - מתודות כמו
test(),match(),replace()מפעילות regex
💡 טיפ: השתמשו בכלים אונליין כמו regex101.com לבדיקה ולימוד של ביטויים רגולריים!