מחלקות ב-JavaScript
מאמר זה מסביר מחלקות ב-JavaScript.
YouTube Video
מחלקות ב-JavaScript
ב-JavaScript, מחלקה משלבת את הרעיון של תכנות מונחה עצמים ומשמשת כתבנית ליצירת אובייקטים. באמצעות מחלקות, ניתן להגדיר באופן תמציתי את התכונות ואת המתודות של אובייקט, ובכך לשפר את יכולת השימוש החוזר ואת ארגון הקוד. תחביר המחלקות הוצג ב-JavaScript במסגרת ES6.
הגדרת מחלקה
מחלקה מוגדרת עם מילת המפתח class
ומאותחלת בדרך כלל באמצעות מתודה שנקראת בנאי (constructor).
1class Person {
2 // Constructor method (called when the class is instantiated)
3 constructor(name, age) {
4 this.name = name; // Property definition
5 this.age = age;
6 }
7
8 // Method definition
9 greet() {
10 return `Hello, my name is ${this.name}`;
11 }
12}
13
14// Instantiation of the class
15const alice = new Person("Alice", 25);
16console.log(alice.greet()); // Hello, my name is Alice
- אנו מגדירים מחלקה באמצעות
class Person
. - ה-
constructor
היא מתודה מיוחדת שנקראת באופן אוטומטי כאשר אובייקט נוצר. - המילה
this
מתייחסת למופע (האובייקט) של המחלקה בתוך המחלקה.
תכונות ומתודות של מחלקה
מחלקה יכולה להגדיר תכונות ו-מתודות. תכונות מייצגות את המאפיינים של אובייקט, ומתודות מייצגות את הפונקציות שיש לו.
1class Car {
2 constructor(brand, model) {
3 this.brand = brand;
4 this.model = model;
5 }
6
7 // Method definition
8 drive() {
9 console.log(`Driving a ${this.brand} ${this.model}`);
10 }
11}
12
13const car1 = new Car("Toyota", "Corolla");
14car1.drive(); // Driving a Toyota Corolla
בדוגמה זו, מחלקת Car
מוגדרת עם תכונות brand
ו-model
ומתודה drive
.
הורשת מחלקות
מחלקות יכולות לרשת ממחלקות אחרות. באמצעות שימוש בהורשה, ניתן ליצור מחלקה חדשה על בסיס מחלקה קיימת ולהוסיף לה פונקציונליות נוספת.
1class Animal {
2 constructor(name) {
3 this.name = name;
4 }
5
6 speak() {
7 console.log(`${this.name} makes a noise`);
8 }
9}
10
11// Inherit from the Animal class
12class Dog extends Animal {
13 constructor(name, breed) {
14 super(name); // Call the constructor of the parent class (Animal)
15 this.breed = breed;
16 }
17
18 // Override the method
19 speak() {
20 console.log(`${this.name} barks`);
21 }
22}
23
24const dog = new Dog("Rex", "German Shepherd");
25dog.speak(); // Rex barks
בדוגמה זו, מחלקת Dog
יורשת ממחלקת Animal
.
- מילת המפתח
extends
משמשת כדי לרשת ממחלקתAnimal
. - בבנאי של מחלקת
Dog
, הפונקציהsuper()
משמשת כדי לקרוא לבנאי של המחלקה האב. דבר זה מאפשר לרשת את תהליך האתחול של המחלקה האב. - בתוך המחלקה היורשת, ניתן להחליף את המתודות של המחלקה האב. בדוגמה זו, במקום "רקס משמיע רעש", מופיע "רקס נובח".
שיטות סטטיות
כאשר מגדירים שיטה סטטית בתוך מחלקה, השיטה מקושרת למחלקה עצמה. ניתן לקרוא לשיטות סטטיות ללא יצירת מופע של המחלקה.
1class MathUtils {
2 // Static method
3 static add(a, b) {
4 return a + b;
5 }
6}
7
8console.log(MathUtils.add(5, 10)); // 15
בדוגמה זו, למחלקה MathUtils
יש שיטה סטטית המוגדרת בשם add
.
- המילה השמורה
static
משמשת כדי להגדיר שיטה סטטית. - שיטות סטטיות אינן שייכות למופעי המחלקה וניתן לקרוא להן ישירות מהמחלקה עצמה.
Getters ו-Setters
על ידי הגדרת getters ו-setters במחלקה, ניתן לארוז את הפעולה של קבלת והגדרת המאפיינים.
1class Rectangle {
2 constructor(width, height) {
3 this.width = width;
4 this.height = height;
5 }
6
7 // Getter
8 get area() {
9 return this.width * this.height;
10 }
11
12 // Setter
13 set widthValue(newWidth) {
14 this.width = newWidth;
15 }
16}
17
18const rect = new Rectangle(10, 20);
19console.log(rect.area); // 200
20
21rect.widthValue = 15;
22console.log(rect.area); // 300
בדוגמה זו, המחלקה Rectangle
מגדירה getter בשם area
ו-setter בשם widthValue
.
- ה-getter (
get
) נקרא כאשר מבקשים לקבל את הערך של מאפיין. - ה-setter (
set
) נקרא כאשר קובעים את הערך של מאפיין.
ממתיק תחביר למחלקות
ב-JavaScript, תחביר המחלקות מיושם פנימית באמצעות פונקציות בבנאי ו-פרוטוטיפים. תחביר המחלקות הוא ממתיק תחבירי לכתיבת הדברים הללו בצורה תמציתית יותר.
1// Example without using class syntax
2function Person(name, age) {
3 this.name = name;
4 this.age = age;
5}
6
7Person.prototype.greet = function() {
8 return `Hello, my name is ${this.name}`;
9};
10
11const person = new Person("Alice", 25);
12console.log(person.greet()); // Hello, my name is Alice
בדוגמה זו, פונקציה בשם Person
מוגדרת בתור בנאי, ושיטה בשם greet
מוגדרת באמצעות פרוטוטיפ.
ניהול this
בתוך מחלקה, המילה this
מתייחסת למופע של המחלקה. עם זאת, כאשר עובדים עם this
בשיטות מחלקה, חשוב להיות מודעים לכך שההתנהגות שלה יכולה להשתנות בהתאם ל-תחום הפעולה. בעיות עלולות להתעורר במיוחד כאשר משתמשים בשיטות בתור פונקציות callback.
1class Counter {
2 constructor() {
3 this.count = 0;
4 }
5
6 increment() {
7 this.count++;
8 console.log(this.count);
9 }
10}
11
12const counter = new Counter();
13setTimeout(counter.increment, 1000); // NaN
14// NaN, since this.count is undefined, it becomes NaN after incrementing.
במקרים כאלה, כאשר מעבירים את השיטה בתור callback ל-setTimeout
, ההפניה של this
עשויה להשתנות. כדי להימנע מבעיה זו, מומלץ או לתקן את this
באמצעות שיטת bind
או להשתמש בפונקציות חץ.
1class Counter {
2 constructor() {
3 this.count = 0;
4 }
5
6 increment() {
7 this.count++;
8 console.log(this.count);
9 }
10}
11
12const counter = new Counter();
13
14// When using bind
15setTimeout(counter.increment.bind(counter), 1000);
16
17// When using an arrow function
18setTimeout(() => counter.increment(), 2000);
סיכום
- מחלקות משמשות כתבניות ליצירת אובייקטים ומגדירות מאפיינים ושיטות.
- ניתן להשתמש ב-הורשה כדי להרחיב מחלקה, תוך שימוש בעקרונות תכנות מונחה עצמים.
- שיטות סטטיות שייכות למחלקה עצמה וניתן להשתמש בהן ללא יצירת מופע.
- ניתן לארוז מאפיינים באמצעות getters ו-setters.
- תחביר המחלקות של JavaScript הוא סוכר תחבירי ומשתמש בתורו בירושה מבוססת-אב טיפוס.
באמצעות שימוש במחלקות, ניתן להתמודד עם תכנות מונחה-עצמים ביתר טבעיות, ולשפר את השימוש החוזר בקוד ואת התחזוקה.
תוכלו לעקוב אחר המאמר שלמעלה באמצעות Visual Studio Code בערוץ היוטיוב שלנו. נא לבדוק גם את ערוץ היוטיוב.