לדלג לתוכן

2.2 משתנים, טיפוסים ואופרטורים הרצאה

משתנים - variables

בפייתון כשרוצים ליצור משתנה פשוט כותבים x = 5. בג׳אווהסקריפט יש שלוש מילים שונות להגדרת משתנים: let, const, ו-var.

let - משתנה שאפשר לשנות

let age = 25;
console.log(age); // 25

age = 26; // ok - we can change it
console.log(age); // 26
  • let מגדיר משתנה שאפשר לשנות את הערך שלו
  • דומה להתנהגות הרגילה של משתנים בפייתון

const - קבוע (לא ניתן לשינוי)

const PI = 3.14159;
console.log(PI); // 3.14159

PI = 3; // ERROR! Assignment to constant variable
  • const מגדיר משתנה שאי אפשר לשנות אחרי ההגדרה
  • חובה לתת ערך מיד בהגדרה
  • בפייתון אין מקבילה אמיתית - יש רק מוסכמה לכתוב שמות בגדול (UPPER_CASE) אבל זה לא אוכף שום דבר
const name = "Alice"; // must assign a value immediately
const x; // ERROR! Missing initializer in const declaration

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

const colors = ["red", "green", "blue"];
colors.push("yellow"); // ok! we're changing the content, not the reference
colors = ["purple"]; // ERROR! can't reassign the variable itself

var - הדרך הישנה (לא להשתמש)

var name = "Alice";
name = "Bob"; // ok
  • var היא הדרך הישנה להגדיר משתנים, מלפני ES6 (2015)
  • היא עדיין עובדת, אבל יש לה כמה בעיות שלמדו מהן
  • אל תשתמשו ב-var - תמיד השתמשו ב-let או const

מה להשתמש?

הכלל פשוט:
1. תמיד תתחילו עם const - רוב המשתנים לא צריכים להשתנות
2. אם אתם צריכים לשנות את הערך, שנו ל-let
3. לעולם אל תשתמשו ב-var

const userName = "Alice"; // won't change - use const
let score = 0;            // will change during the game - use let
score += 10;

הרמה - hoisting

Hoisting הוא התנהגות מיוחדת של JavaScript שמעלה הגדרות משתנים לתחילת ה-scope:

console.log(x); // undefined (not an error!)
var x = 5;

console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 5;
  • var עובר hoisting - ההגדרה עולה למעלה, אבל הערך לא. לכן מקבלים undefined
  • let ו-const נמצאים ב-"אזור מת זמני" (Temporal Dead Zone) - אי אפשר לגשת אליהם לפני ההגדרה
  • זו עוד סיבה להימנע מ-var
  • בפייתון אין hoisting - אם תנסו להשתמש במשתנה לפני שהגדרתם אותו, תקבלו NameError

מוסכמת שמות - naming conventions

// JavaScript - camelCase
let firstName = "Alice";
let maxRetryCount = 3;
let isLoggedIn = true;

// Python - snake_case
// first_name = "Alice"
// max_retry_count = 3
// is_logged_in = True
  • בג׳אווהסקריפט משתמשים ב-camelCase: המילה הראשונה קטנה, כל מילה חדשה מתחילה באות גדולה
  • בפייתון משתמשים ב-snake_case: כל המילים קטנות, מופרדות בקו תחתון
  • קבועים בשתי השפות בדרך כלל ב-UPPER_CASE: const MAX_SIZE = 100;

טיפוסי נתונים - data types

בג׳אווהסקריפט יש 7 טיפוסים פרימיטיביים (primitive types):

מחרוזת - string

const greeting = "Hello";       // double quotes
const name = 'Alice';           // single quotes
const message = `Hi ${name}!`;  // template literal (backticks)
  • שלוש דרכים ליצור מחרוזות: גרשיים כפולים, גרשיים בודדים, ו-backticks
  • backticks מאפשרים ביטויים בתוך המחרוזת עם ${} - דומה ל-f-strings בפייתון
// JavaScript template literal
let age = 25;
console.log(`I am ${age} years old`);

// Python f-string equivalent
// print(f"I am {age} years old")

מספר - number

const integer = 42;
const decimal = 3.14;
const negative = -10;
  • בפייתון יש int ו-float - שני טיפוסים נפרדים
  • בג׳אווהסקריפט יש רק number - הוא מכסה גם מספרים שלמים וגם עשרוניים
  • זו הפשטה נוחה, אבל לפעמים גורמת להפתעות:
console.log(0.1 + 0.2); // 0.30000000000000004 (not 0.3!)
// same issue exists in Python with floats

בוליאני - boolean

const isActive = true;
const isDeleted = false;
  • שימו לב: true ו-false באותיות קטנות - לא True ו-False כמו בפייתון!

null

const result = null;
  • null אומר "אין ערך" - במכוון. המתכנת החליט ששם אין ערך
  • דומה ל-None בפייתון

undefined

let x;
console.log(x); // undefined
  • undefined אומר "המשתנה הוגדר אבל לא קיבל ערך"
  • אין מקבילה בפייתון - בפייתון אם לא נותנים ערך, מקבלים שגיאה
  • זה אחד ההבדלים המבלבלים: null הוא "אין ערך במכוון", undefined הוא "עוד לא הוגדר ערך"

symbol

const id = Symbol("id");
  • ערך ייחודי שלא שווה לשום דבר אחר
  • שימוש מתקדם - לא נרחיב עליו כרגע

bigint

const huge = 9007199254740991n; // note the 'n' at the end
  • מספרים שלמים גדולים מאוד
  • שימוש נדיר - לא נרחיב עליו כרגע

האופרטור typeof

console.log(typeof "hello");    // "string"
console.log(typeof 42);         // "number"
console.log(typeof true);       // "boolean"
console.log(typeof undefined);  // "undefined"
console.log(typeof null);       // "object" (this is a known bug!)
console.log(typeof Symbol());   // "symbol"
  • typeof מחזיר מחרוזת עם שם הטיפוס
  • באג ידוע: typeof null מחזיר "object" במקום "null" - זו טעות מ-1995 שאי אפשר לתקן כי זה ישבור אתרים קיימים

בפייתון המקבילה היא type():

// JavaScript
typeof 42         // "number"

// Python
// type(42)       // <class 'int'>


המרת טיפוסים - type coercion

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

המרה אוטומטית (החלקים המוזרים)

// string + number = string (concatenation wins)
console.log("5" + 3);     // "53" (not 8!)
console.log("Hello" + 5); // "Hello5"

// string - number = number (math wins)
console.log("5" - 3);     // 2
console.log("10" * 2);    // 20
console.log("10" / 2);    // 5

// other weird ones
console.log(true + 1);    // 2 (true becomes 1)
console.log(false + 1);   // 1 (false becomes 0)
console.log("" + 0);      // "0"
console.log(null + 1);    // 1 (null becomes 0)
console.log(undefined + 1); // NaN

הכלל: כשמשתמשים ב-+ ואחד הצדדים הוא מחרוזת, JS ממיר הכל למחרוזת ומשרשר. עם אופרטורים אחרים (-, *, /), JS מנסה להמיר הכל למספר.

בפייתון זה פשוט יותר - "5" + 3 יזרוק TypeError. פייתון לא מנחש מה התכוונתם.

המרה מפורשת - explicit conversion

כדי להמיר בצורה מכוונת ובטוחה:

// to number
Number("42");      // 42
Number("hello");   // NaN
Number(true);      // 1
Number(false);     // 0
Number(null);      // 0
Number(undefined); // NaN

// to string
String(42);        // "42"
String(true);      // "true"
String(null);      // "null"

// to boolean
Boolean(1);        // true
Boolean(0);        // false
Boolean("");       // false
Boolean("hello");  // true

בפייתון זה דומה: int("42"), str(42), bool(0).


ערכים אמיתיים ושקריים - truthy and falsy

כל ערך בג׳אווהסקריפט הוא "אמיתי" (truthy) או "שקרי" (falsy) כשממירים אותו לבוליאני.

ערכים שקריים - falsy values

יש בדיוק 6 ערכים שקריים:

Boolean(false);     // false
Boolean(0);         // false
Boolean("");        // false (empty string)
Boolean(null);      // false
Boolean(undefined); // false
Boolean(NaN);       // false

כל השאר הוא truthy - כולל דברים שאולי לא ציפיתם:

Boolean("0");       // true (non-empty string!)
Boolean(" ");       // true (string with space)
Boolean([]);        // true (empty array!)
Boolean({});        // true (empty object!)
Boolean("false");   // true (the string "false", not the boolean)

שימו לב להבדל מפייתון:
- בפייתון, רשימה ריקה [] ומילון ריק {} הם falsy
- בג׳אווהסקריפט, מערך ריק [] ואובייקט ריק {} הם truthy!

// JavaScript
if ([]) {
    console.log("empty array is truthy in JS!"); // this WILL run
}

// Python
// if []:
//     print("this won't run - empty list is falsy in Python")

NaN ו-Infinity

console.log(0 / 0);          // NaN (Not a Number)
console.log("hello" * 2);    // NaN
console.log(NaN === NaN);    // false! (NaN is not equal to itself)
console.log(isNaN(NaN));     // true (use isNaN to check)
console.log(Number.isNaN(NaN)); // true (more reliable)

console.log(1 / 0);          // Infinity
console.log(-1 / 0);         // -Infinity
  • NaN הוא ערך מיוחד שאומר "זה לא מספר תקין"
  • הוא הערך היחיד שלא שווה לעצמו!
  • בפייתון 0 / 0 זורק ZeroDivisionError, בJS מקבלים NaN

השוואה לפייתון

ערך Python JavaScript
ערך ריק None null / undefined
אמת/שקר True / False true / false
int/float int, float number (אחד לכולם)
רשימה ריקה falsy? כן לא ([] truthy)
מילון ריק falsy? כן לא ({} truthy)

אופרטורים - operators

אופרטורים אריתמטיים

console.log(10 + 3);  // 13   addition
console.log(10 - 3);  // 7    subtraction
console.log(10 * 3);  // 30   multiplication
console.log(10 / 3);  // 3.333...  division (always float!)
console.log(10 % 3);  // 1    modulo (remainder)
console.log(10 ** 3); // 1000 exponentiation
  • אלה זהים לפייתון, חוץ מחילוק
  • בפייתון 10 / 3 נותן 3.333... ו-10 // 3 נותן 3 (חילוק שלם)
  • בJS אין אופרטור // לחילוק שלם - משתמשים ב-Math.floor(10 / 3) במקום
// JavaScript - no integer division operator
console.log(Math.floor(10 / 3)); // 3

// Python
// 10 // 3  # 3

אופרטורי השמה

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
  • זהה לפייתון

בנוסף, לJS יש אופרטורים שאין בפייתון:

let count = 0;
count++;   // count = count + 1 -> 1
count++;   // -> 2
count--;   // count = count - 1 -> 1
  • ++ מעלה ב-1, -- מוריד ב-1
  • בפייתון אין ++ ו---, משתמשים ב-count += 1

אופרטורי השוואה - == מול === (חשוב מאוד!)

זה אחד הדברים הכי חשובים בג׳אווהסקריפט:

// == (loose equality) - converts types before comparing
console.log(5 == "5");     // true! (string "5" converted to number 5)
console.log(0 == false);   // true! (false converted to 0)
console.log(null == undefined); // true!
console.log("" == 0);      // true!

// === (strict equality) - no type conversion
console.log(5 === "5");    // false (different types)
console.log(0 === false);  // false (different types)
console.log(null === undefined); // false (different types)
console.log("" === 0);     // false (different types)
  • == (השוואה רופפת) ממיר טיפוסים לפני ההשוואה - זה גורם לתוצאות מפתיעות
  • === (השוואה מחמירה) לא ממיר - שני הערכים חייבים להיות מאותו טיפוס וגם שווים
  • תמיד תשתמשו ב-=== (ו-!== במקום !=)

בפייתון == משווה ערכים ו-is משווה זהות (האם זה אותו אובייקט). ב-JS === הוא מה שצריך.

// ALWAYS use these:
console.log(5 === 5);     // true
console.log(5 !== "5");   // true

// NEVER use these:
// console.log(5 == "5");  // avoid!
// console.log(5 != "5");  // avoid!

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

// && (AND) - equivalent to Python's "and"
console.log(true && true);   // true
console.log(true && false);  // false

// || (OR) - equivalent to Python's "or"
console.log(true || false);  // true
console.log(false || false); // false

// ! (NOT) - equivalent to Python's "not"
console.log(!true);  // false
console.log(!false); // true

בפייתון:

# Python uses words
# True and False   -> False
# True or False    -> True
# not True         -> False

ב-JS משתמשים בסימנים &&, ||, ! - לא במילים and, or, not.

הערכה מקוצרת - short-circuit evaluation

בדיוק כמו בפייתון, האופרטורים הלוגיים מחזירים את הערך עצמו, לא בהכרח true/false:

// || returns the first truthy value (or the last value)
console.log("hello" || "world"); // "hello"
console.log("" || "default");   // "default"
console.log(0 || 42);           // 42
console.log(null || "fallback"); // "fallback"

// && returns the first falsy value (or the last value)
console.log("hello" && "world"); // "world"
console.log("" && "world");     // ""
console.log(null && "hello");   // null

שימוש נפוץ - ערך ברירת מחדל:

let name = userInput || "Anonymous";
// if userInput is falsy (empty string, null, undefined), use "Anonymous"

בפייתון:

# name = user_input or "Anonymous"

אופרטור nullish coalescing - ??

זה אופרטור חדש (ES2020) שלא קיים בפייתון:

// ?? returns the right side only if the left is null or undefined
let name = null ?? "Anonymous";     // "Anonymous"
let age = undefined ?? 18;          // 18
let score = 0 ?? 100;              // 0 (0 is NOT null/undefined!)
let text = "" ?? "default";        // "" (empty string is NOT null/undefined!)

ההבדל מ-||:

// || treats 0, "", false as falsy - replaces them too
let score1 = 0 || 100;  // 100 (0 is falsy, so it uses 100)

// ?? only replaces null and undefined
let score2 = 0 ?? 100;  // 0 (0 is not null/undefined, so it stays)

  • || מחליף כל ערך falsy (0, "", false, null, undefined)
  • ?? מחליף רק null ו-undefined
  • ?? בטוח יותר כשיש ערכים כמו 0 או מחרוזת ריקה שהם לגיטימיים

שרשור אופציונלי - optional chaining (?.)

גם זה חדש ולא קיים בפייתון:

const user = {
    name: "Alice",
    address: {
        city: "Tel Aviv"
    }
};

// without optional chaining - can crash!
// console.log(user.phone.number); // TypeError: Cannot read property 'number' of undefined

// with optional chaining - safe!
console.log(user.phone?.number); // undefined (no error)
console.log(user.address?.city); // "Tel Aviv"
  • ?. בודק אם הערך שמשמאל הוא null או undefined
  • אם כן, מחזיר undefined בלי לזרוק שגיאה
  • אם לא, ממשיך לגשת למאפיין

בפייתון צריך לעשות את זה ידנית:

# Python - no optional chaining
# city = user.get("address", {}).get("city")
# or
# city = user.address.city if user.address else None

אופרטור תלת-תנאי - ternary operator

let age = 20;
let status = age >= 18 ? "adult" : "minor";
console.log(status); // "adult"
  • התחביר: condition ? valueIfTrue : valueIfFalse
  • זה קיצור ל-if/else שמחזיר ערך

בפייתון המקבילה:

# status = "adult" if age >= 18 else "minor"

שימו לב שסדר המילים שונה! בJS התנאי ראשון, בפייתון הערך ראשון.

// useful for quick assignments
let greeting = hour < 12 ? "Good morning" : "Good evening";
let display = isVisible ? "block" : "none";
let label = count === 1 ? "item" : "items";

typeof ו-instanceof

// typeof - check primitive types
console.log(typeof "hello");  // "string"
console.log(typeof 42);       // "number"
console.log(typeof true);     // "boolean"

// instanceof - check if object is instance of a class (for later)
console.log([] instanceof Array);   // true
console.log({} instanceof Object);  // true

בפייתון:

# type("hello")       # <class 'str'>
# isinstance([], list) # True


סיכום

  • משתמשים ב-const כברירת מחדל, let כשצריך לשנות, לעולם לא var
  • ב-JS יש number אחד בלבד - אין int/float נפרדים
  • null = "אין ערך במכוון", undefined = "לא הוגדר ערך"
  • type coercion היא מוזרה - "5" + 3 נותן "53", "5" - 3 נותן 2
  • תמיד השתמשו ב-=== ולא ב-==
  • ?? עדיף על || כשערכים כמו 0 או "" הם לגיטימיים
  • ?. מונע שגיאות כשניגשים למאפיינים שאולי לא קיימים
  • ערכים falsy: false, 0, "", null, undefined, NaN - כל השאר truthy