תחביר וצורת כתיבה

זהו המדריך העיקרי לתחביר של JavaScript ב-Node.js, עם דגש על צורת כתיבה נכונה ומוסכמות מקובלות.


משתנים

שלוש דרכים להגדיר משתנים

// ❌ var - הדרך הישנה, לא מומלץ להשתמש
var oldWay = 'לא מומלץ';

// ✅ let - משתנה שאפשר לשנות
let counter = 0;
counter = 1;  // תקין

// ✅ const - קבוע שלא ניתן לשנות
const PI = 3.14159;
// PI = 3;  // ❌ שגיאה!

// 🔑 כלל הזהב: השתמשו ב-const כברירת מחדל, let רק כשצריך לשנות

הבדלי Scope

// var - function scope (בעייתי!)
function varExample() {
    if (true) {
        var x = 10;
    }
    console.log(x);  // 10 - עדיין נגיש!
}

// let/const - block scope (טוב יותר)
function letExample() {
    if (true) {
        let y = 10;
    }
    // console.log(y);  // ❌ שגיאה! y לא מוגדר כאן
}

טיפוסי נתונים

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

// String - מחרוזת
const name = 'ישראל';
const greeting = "שלום";
const template = `שלום ${name}!`;  // Template Literal

// Number - מספר (שלם או עשרוני)
const age = 30;
const price = 19.99;
const negative = -5;

// Boolean - ערך לוגי
const isActive = true;
const isDeleted = false;

// undefined - לא הוגדר ערך
let notDefined;
console.log(notDefined);  // undefined

// null - ערך ריק במכוון
const emptyValue = null;

// Symbol - ייחודי ובלתי ניתן לשינוי
const uniqueId = Symbol('id');

// BigInt - מספרים גדולים מאוד
const bigNumber = 9007199254740991n;

בדיקת טיפוס

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

מחרוזות (Strings)

יצירה ופעולות בסיסיות

const str = 'שלום עולם';

// אורך
console.log(str.length);  // 9

// גישה לתו
console.log(str[0]);  // 'ש'
console.log(str.charAt(0));  // 'ש'

// חיפוש
console.log(str.includes('עולם'));  // true
console.log(str.indexOf('עולם'));   // 5
console.log(str.startsWith('שלום')); // true
console.log(str.endsWith('עולם'));   // true

// חיתוך
console.log(str.slice(0, 4));  // 'שלום'
console.log(str.substring(5)); // 'עולם'

// שינוי
console.log(str.toUpperCase());  // 'שלום עולם' (לא משפיע על עברית)
console.log(str.replace('עולם', 'ישראל'));  // 'שלום ישראל'
console.log('  hello  '.trim());  // 'hello'

// פיצול
console.log('a,b,c'.split(','));  // ['a', 'b', 'c']

Template Literals (מחרוזות תבנית)

const name = 'משה';
const age = 30;

// הדרך הישנה
const old = 'שם: ' + name + ', גיל: ' + age;

// ✅ הדרך החדשה והמומלצת
const modern = `שם: ${name}, גיל: ${age}`;

// מספר שורות
const multiLine = `
    שורה ראשונה
    שורה שנייה
    שורה שלישית
`;

// חישובים בתוך ${}
console.log(`2 + 2 = ${2 + 2}`);  // 2 + 2 = 4
console.log(`גיל בעוד 10 שנים: ${age + 10}`);

מערכים (Arrays)

יצירה ופעולות בסיסיות

// Create
const fruits = ['תפוח', 'בננה', 'תפוז'];
const numbers = [1, 2, 3, 4, 5];
const mixed = [1, 'hello', true, null];

// גישה
console.log(fruits[0]);   // 'תפוח'
console.log(fruits.length); // 3

// הוספה והסרה
fruits.push('ענבים');      // הוספה לסוף
fruits.unshift('אבטיח');   // הוספה להתחלה
fruits.pop();              // הסרה מסוף
fruits.shift();            // הסרה מהתחלה

// חיפוש
console.log(fruits.includes('בננה'));  // true
console.log(fruits.indexOf('בננה'));   // 1
console.log(fruits.find(f => f === 'בננה'));  // 'בננה'

מתודות מערך חיוניות

const numbers = [1, 2, 3, 4, 5];

// map - יוצר מערך חדש עם תוצאות הפונקציה
const doubled = numbers.map(n => n * 2);
// [2, 4, 6, 8, 10]

// filter - מסנן לפי תנאי
const evens = numbers.filter(n => n % 2 === 0);
// [2, 4]

// reduce - מצמצם לערך אחד
const sum = numbers.reduce((acc, n) => acc + n, 0);
// 15

// forEach - לולאה על כל איבר
numbers.forEach(n => console.log(n));

// find - מוצא את האיבר הראשון שעונה לתנאי
const firstEven = numbers.find(n => n % 2 === 0);
// 2

// some/every - בדיקות
console.log(numbers.some(n => n > 3));   // true - האם יש לפחות אחד?
console.log(numbers.every(n => n > 0));  // true - האם כולם?

// sort - מיון
const sorted = [...numbers].sort((a, b) => b - a);  // יורד
// [5, 4, 3, 2, 1]

אובייקטים (Objects)

יצירה ושימוש

// Basic Create
const user = {
    name: 'ישראל ישראלי',
    age: 30,
    email: '[email protected]',
    isActive: true
};

// גישה לערכים
console.log(user.name);       // ישראל ישראלי (dot notation)
console.log(user['name']);    // ישראל ישראלי (bracket notation)

// שינוי ערכים
user.age = 31;
user['email'] = '[email protected]';

// הוספת שדות
user.phone = '050-1234567';

// מחיקת שדות
delete user.phone;

// בדיקה אם שדה קיים
console.log('name' in user);           // true
console.log(user.hasOwnProperty('name')); // true

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

const user = {
    firstName: 'ישראל',
    lastName: 'ישראלי',

    // מתודה - פונקציה בתוך אובייקט
    getFullName() {
        return `${this.firstName} ${this.lastName}`;
    },

    // גרסה ישנה יותר (עדיין עובד)
    greet: function() {
        console.log(`שלום, אני ${this.firstName}`);
    }
};

console.log(user.getFullName());  // ישראל ישראלי
user.greet();  // שלום, אני ישראל

פעולות על אובייקטים

const user = { name: 'ישראל', age: 30 };

// קבלת מפתחות/ערכים/זוגות
Object.keys(user);    // ['name', 'age']
Object.values(user);  // ['ישראל', 30]
Object.entries(user); // [['name', 'ישראל'], ['age', 30]]

// מיזוג אובייקטים
const defaults = { theme: 'dark', lang: 'he' };
const settings = { lang: 'en' };
const merged = { ...defaults, ...settings };
// { theme: 'dark', lang: 'en' }

// העתקה (שטחית)
const copy = { ...user };
const copy2 = Object.assign({}, user);

פונקציות

סוגי פונקציות

// 1. Function Declaration - הגדרת פונקציה
function greet(name) {
    return `שלום ${name}!`;
}

// 2. Function Expression - ביטוי פונקציה
const greet2 = function(name) {
    return `שלום ${name}!`;
};

// 3. Arrow Function - פונקציית חץ (הכי נפוצה)
const greet3 = (name) => {
    return `שלום ${name}!`;
};

// Arrow Function מקוצרת (לשורה אחת)
const greet4 = (name) => `שלום ${name}!`;

// Arrow Function עם פרמטר אחד (בלי סוגריים)
const greet5 = name => `שלום ${name}!`;

פרמטרים וערכי ברירת מחדל

// Default Parameters
function greet(name = 'אורח') {
    console.log(`שלום ${name}!`);
}
greet();        // שלום אורח!
greet('משה');  // שלום משה!

// Rest parameters - מספר לא ידוע של פרמטרים
function sum(...numbers) {
    return numbers.reduce((acc, n) => acc + n, 0);
}
console.log(sum(1, 2, 3, 4));  // 10

// Destructuring בפרמטרים
function printUser({ name, age }) {
    console.log(`${name} בן ${age}`);
}
printUser({ name: 'ישראל', age: 30 });

Arrow Functions ו-this

// This ⚠️ הבדל חשוב!
const obj = {
    name: 'ישראל',

    // פונקציה רגילה - this מצביע על האובייקט
    regularFunc: function() {
        console.log(this.name);  // ישראל
    },

    // Arrow function - this מצביע על ההקשר החיצוני
    arrowFunc: () => {
        console.log(this.name);  // undefined!
    }
};

// 🔑 כלל הזהב: למתודות באובייקט, השתמשו בפונקציות רגילות
// ל-callbacks, השתמשו ב-Arrow Functions

תנאים

if / else if / else

const age = 18;

if (age < 13) {
    console.log('ילד');
} else if (age < 20) {
    console.log('נער');
} else if (age < 60) {
    console.log('מבוגר');
} else {
    console.log('קשיש');
}

Ternary Operator (אופרטור תנאי)

const age = 18;
const status = age >= 18 ? 'מבוגר' : 'קטין';
console.log(status);  // מבוגר

// אפשר לשרשר (אבל לא מומלץ - קשה לקריאה)
const category = age < 13 ? 'ילד' : age < 20 ? 'נער' : 'מבוגר';

switch

const day = 'שני';

switch (day) {
    case 'ראשון':
        console.log('תחילת השבוע');
        break;
    case 'שישי':
    case 'שבת':
        console.log('סוף שבוע!');
        break;
    default:
        console.log('יום רגיל');
}

Nullish Coalescing (??)

// Nullish ?? - מחזיר את הערך הימני רק אם השמאלי הוא null או undefined
const userInput = null;
const defaultValue = userInput ?? 'ערך ברירת מחדל';
console.log(defaultValue);  // 'ערך ברירת מחדל'

// הבדל מ-||
const count1 = 0 || 10;   // 10 (כי 0 הוא falsy)
const count2 = 0 ?? 10;   // 0 (כי 0 הוא לא null/undefined)

Optional Chaining (?.)

const user = {
    name: 'ישראל',
    address: {
        city: 'תל אביב'
    }
};

// בלי Optional Chaining - יכול לזרוק שגיאה
// console.log(user.contact.phone);  // ❌ Error!

// עם Optional Chaining - בטוח
console.log(user.contact?.phone);  // undefined
console.log(user.address?.city);   // 'תל אביב'

// שילוב עם ??
const phone = user.contact?.phone ?? 'לא צוין';

לולאות

for הקלאסית

for (let i = 0; i < 5; i++) {
    console.log(i);  // 0, 1, 2, 3, 4
}

// לולאה הפוכה
for (let i = 4; i >= 0; i--) {
    console.log(i);  // 4, 3, 2, 1, 0
}

for...of (למערכים וiterables)

const fruits = ['תפוח', 'בננה', 'תפוז'];

for (const fruit of fruits) {
    console.log(fruit);
}
// תפוח
// בננה
// תפוז

// עם אינדקס
for (const [index, fruit] of fruits.entries()) {
    console.log(`${index}: ${fruit}`);
}

for...in (לאובייקטים)

const user = { name: 'ישראל', age: 30 };

for (const key in user) {
    console.log(`${key}: ${user[key]}`);
}
// name: ישראל
// age: 30

while ו-do...while

// while
let count = 0;
while (count < 3) {
    console.log(count);
    count++;
}

// do...while - מבצע לפחות פעם אחת
let num = 0;
do {
    console.log(num);
    num++;
} while (num < 3);

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

try...catch...finally

try {
    // קוד שעלול לזרוק שגיאה
    const result = JSON.parse('לא JSON תקין');
} catch (error) {
    // טיפול בשגיאה
    console.error('שגיאה:', error.message);
} finally {
    // מתבצע תמיד, גם אם הייתה שגיאה וגם אם לא
    console.log('סיום');
}

זריקת שגיאות

function divide(a, b) {
    if (b === 0) {
        throw new Error('לא ניתן לחלק באפס!');
    }
    return a / b;
}

try {
    const result = divide(10, 0);
} catch (error) {
    console.error(error.message);  // לא ניתן לחלק באפס!
}

סוגי שגיאות

// error שגיאה כללית
throw new Error('משהו השתבש');

// שגיאת טיפוס
throw new TypeError('צפוי מספר');

// שגיאת טווח
throw new RangeError('הערך חורג מהטווח');

// שגיאת syntax (לא ניתן לזרוק ידנית בזמן ריצה)
// throw new SyntaxError('syntax שגוי');

Destructuring (פירוק)

פירוק אובייקטים

const user = { name: 'ישראל', age: 30, city: 'תל אביב' };

// הדרך הישנה
const name1 = user.name;
const age1 = user.age;

// ✅ Destructuring
const { name, age, city } = user;
console.log(name, age, city);  // ישראל 30 תל אביב

// עם שם חדש
const { name: userName, age: userAge } = user;

// עם ערך ברירת מחדל
const { country = 'ישראל' } = user;

// פירוק מקונן
const response = { data: { users: [{ id: 1 }] } };
const { data: { users } } = response;

פירוק מערכים

const colors = ['אדום', 'ירוק', 'כחול'];

// הדרך הישנה
const first1 = colors[0];
const second1 = colors[1];

// ✅ Destructuring
const [first, second, third] = colors;
console.log(first, second);  // אדום ירוק

// דילוג על ערכים
const [, , blue] = colors;  // רק הכחול

// Rest
const [head, ...rest] = colors;
console.log(rest);  // ['ירוק', 'כחול']

// החלפת ערכים
let a = 1, b = 2;
[a, b] = [b, a];  // עכשיו a=2, b=1

Spread Operator (...)

במערכים

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

// איחוד מערכים
const combined = [...arr1, ...arr2];  // [1, 2, 3, 4, 5, 6]

// העתקת מערך
const copy = [...arr1];

// הוספת ערכים
const withExtra = [0, ...arr1, 4];  // [0, 1, 2, 3, 4]

באובייקטים

const defaults = { theme: 'dark', lang: 'he' };
const userPrefs = { lang: 'en' };

// מיזוג (הערכים האחרונים גוברים)
const settings = { ...defaults, ...userPrefs };
// { theme: 'dark', lang: 'en' }

// העתקה והוספה
const newSettings = { ...settings, fontSize: 16 };

בקריאה לפונקציות

const numbers = [1, 2, 3];

// במקום apply
console.log(Math.max(...numbers));  // 3

function greet(a, b, c) {
    console.log(a, b, c);
}
greet(...numbers);  // 1 2 3

מוסכמות שמות

// camelCase - משתנים ופונקציות
const userName = 'ישראל';
function getUserById(id) { }

// קבועים - UPPER_SNAKE_CASE
const MAX_RETRIES = 3;
const API_BASE_URL = 'https://api.example.com';

// קלאסים - PascalCase
class UserAccount { }
class HttpClient { }

// קבצים - kebab-case או camelCase
// user-service.js או userService.js

// פרמטרים פרטיים (מוסכמה) - קו תחתון
class User {
    _privateField = 'פרטי';
}

// שמות משמעותיים
// ❌ לא טוב
const x = users.filter(u => u.a > 18);

// ✅ טוב
const adultUsers = users.filter(user => user.age > 18);

סיכום מהיר

נושא דוגמה
משתנים const x = 1; let y = 2;
פונקציית חץ const fn = (x) => x * 2;
Template Literal `שלום ${name}`
Destructuring const { a, b } = obj;
Spread [...arr1, ...arr2]
Optional Chaining obj?.prop?.value
Nullish Coalescing value ?? 'default'

← חזרה ליסודות | → המשך למודולים

בדקו את עצמכם

נסו לענות לבד לפני שאתם פותחים את התשובה.

  1. איך כותבים מחרוזת עם משתנה בתוכה?

    1. "שלום" + {name}
    2. 'שלום ${name}'
    3. 'שלום' . name
    4. `שלום ${name}`
    הצגת התשובה

    תשובה ד. Template literal עם גרש הפוך מאפשר ${} בתוך המחרוזת.

  2. מה עושה const { name, ...rest } = user?

    1. לוקח את name לחוד, ואת שאר השדות לאובייקט rest
    2. מעתיק את user
    3. מוחק את name
    4. שגיאה
    הצגת התשובה

    תשובה א. פירוק עם rest: שימושי כשרוצים להוציא שדה אחד.