תכונות נוספות של מחלקות בג'אווהסקריפט
במאמר זה, נסביר את התכונות הנוספות של מחלקות בג'אווהסקריפט.
YouTube Video
תכונות נוספות של מחלקות בג'אווהסקריפט
מאפיינים פרטיים בג'אווהסקריפט
בג'אווהסקריפט, מאפיינים פרטיים הם מאפיינים שנגישים רק בתוך האובייקט או המחלקה. זה מאפשר תכנון קוד מאובטח וחזק יותר על ידי מתן כימוס, כך שלא ניתן לבצע שינוי ישיר או הפניה מקוד חיצוני.
הוצג ב-ECMAScript 2020 (ES11) בשנת 2020, השימוש ב-#
(האשטאג) להגדרת שדות פרטיים בתוך מחלקה. זה מספק דרך ברורה יותר, במקום מוסכמות פרטיות מסורתיות בג'אווהסקריפט (כמו שמות משתנים שמתחילים בקו תחתון).
יתרונות של מאפיינים פרטיים
היתרונות של מאפיינים פרטיים הם הבאים.
- כמוסה (Encapsulation): מסתירה את מצב הפנים מהחוץ ושומרת על עקביות נתונים.
- אבטחה: מונע שינויים לא מכוונים במאפיינים מקוד חיצוני.
- תחזוקה משופרת: מסתירה את המימוש של אובייקטים או מחלקות ומבהירה את הממשק הנחשף כלפי חוץ.
כיצד להשתמש במאפיינים פרטיים
הגדרת מאפיינים פרטיים במחלקות
שדות פרטיים מוגדרים באמצעות שם שמתחיל ב-#
. לא ניתן לגשת לשדה זה ישירות ממופעים של המחלקה או מתתי המחלקות שלה.
1class Person {
2 // Define private property
3 #name;
4
5 constructor(name) {
6 this.#name = name;
7 }
8
9 // Method to access the private property
10 getName() {
11 return this.#name;
12 }
13
14 // Method to change the private property
15 setName(newName) {
16 this.#name = newName;
17 }
18}
19
20const john = new Person("John");
21console.log(john.getName()); // John
22
23// Cannot access private property directly
24console.log(john.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class
בקוד למעלה, #name
הוא מאפיין פרטי שלא ניתן לגשת אליו ישירות מחוץ למחלקת Person
. ניתן לגשת או לשנות את השם רק באמצעות השיטות getName
ו-setName
.
הגדרת שיטות פרטיות
כמו מאפיינים פרטיים, גם שיטות פרטיות מוגדרות באמצעות שם שמתחיל ב-#
. ניתן לקרוא לשיטות פרטיות רק מתוך המחלקה.
1class Counter {
2 #count = 0;
3
4 increment() {
5 this.#count++;
6 this.#logCount(); // Calling private method
7 }
8
9 // Private method
10 #logCount() {
11 console.log(`Current count: ${this.#count}`);
12 }
13}
14
15const counter = new Counter();
16counter.increment(); // Current count: 1
17
18// Cannot access private method directly
19counter.#logCount(); // SyntaxError: Private field '#logCount' must be declared in an enclosing class
כאן, #logCount
מוגדר כשיטה פרטית ולא ניתן לגשת אליו מחוץ למחלקה. שיטה זו משמשת רק בתוך המחלקה.
יתרונות ושיקולים של מאפיינים פרטיים
יתרון
- מכיוון שלא ניתן לגשת אליו ישירות מחוץ למחלקה, נמנעים שינויים או פעולות שאינם מכוונים.
- מכיוון שחלקים שאינם נראים מבחוץ יכולים להיות מוסתרים היטב, ניתן לנהל בבירור את החלקים שאתה חושף כ-API.
הערות
- מכיוון ששדות פרטיים מוסתרים לחלוטין מחוץ למחלקה, בדיקות וניפוי שגיאות יכולים להפוך לקשים. לכן, חשוב לספק API שניתן לבדוק אותו בצורה יסודית בשלב התכנון.
- שדות פרטיים מתנהגים אחרת מחלקים אחרים ב-JavaScript בעלי מאפיינים מבוססי פרוטוטיפ, מכיוון שהם ייחודיים לכל מופע.
מימוש פסאודו-מסורתי של מאפיינים פרטיים
לפני הצגת השדות הפרטיים באמצעות #
, ל-JavaScript לא הייתה תחביר רשמי למאפיינים פרטיים. לכן, בעבר מומשו מאפיינים פסאודו-פרטיים בדרכים הבאות.
שימוש בקו תחתון לפי מוסכמה
מפתחים בדרך כלל סימנו 'פרטי' על ידי הוספת קו תחתון לפני שמות משתנים.
1class Car {
2 constructor(brand) {
3 this._brand = brand; // Using an underscore to indicate private
4 }
5
6 getBrand() {
7 return this._brand;
8 }
9}
10
11const car = new Car("Toyota");
12console.log(car.getBrand()); // Toyota
13console.log(car._brand); // Toyota (Accessible from outside)
שיטה זו היא רק 'מוסכמה', ובפועל ניתן עדיין לגשת למאפיינים מבחוץ.
מימוש מאפיינים פרטיים באמצעות סוגרים (closures)
ניתן גם להשיג מאפיינים פרטיים באמצעות סוגרים עם טווח פונקציה.
1function createPerson(name) {
2 let _name = name; // Private variable within function scope
3
4 return {
5 getName: function() {
6 return _name;
7 },
8 setName: function(newName) {
9 _name = newName;
10 }
11 };
12}
13
14const person = createPerson("Alice");
15console.log(person.getName()); // Alice
16person.setName("Bob");
17console.log(person.getName()); // Bob
18
19// Cannot access directly from outside
20console.log(person._name); // undefined
בשיטה זו, המשתנה _name
נסגר בתוך טווח הפונקציה ולא ניתן לגשת אליו ישירות מבחוץ.
סיכום
מאפיינים פרטיים ב-JavaScript יעילים מאוד לספק הכמסה בעיצוב כיתות ואובייקטים, ומסייעים בהגנה על נתונים בבטחה. התחביר #
לשדות פרטיים שהוצג ב-ES2020 מספק שיטה ברורה ובטוחה יותר לניהול פרטיות בהשוואה למוסכמות וסוגרים מסורתיים.
Optional Chaining ב-JavaScript
Optional Chaining הוא תחביר שימושי מאוד ב-JavaScript לגישה למאפיינים של אובייקטים מקוננים. הוא משפר את קריאות ונוחות תחזוקת הקוד על ידי מתן גישה בטוחה ללא צורך לבדוק בנפרד את קיומם של מאפיינים מסוימים.
תחביר בסיסי של Optional Chaining
ניתן להשתמש ב-Optional Chaining על ידי הוספת ?
לפני הנקודה (.
) או הסוגריים לגישה למאפיינים. תחביר זה מחזיר undefined
כאשר מאפיין שנסרק הוא null
או undefined
, ומאפשר להמשך עיבוד התוכנית בבטחה מבלי לזרוק שגיאה.
דוגמה:
1const user = {
2 name: 'John',
3 address: {
4 street: '123 Main St',
5 city: 'New York'
6 }
7};
8
9// Without using optional chaining
10const city = user && user.address && user.address.city;
11console.log(city); // New York
12
13// Using optional chaining
14const cityWithOptionalChaining = user?.address?.city;
15console.log(cityWithOptionalChaining); // New York
בדוגמה זו, אנו ניגשים ל-address
ולמאפיין city
שלו מתוך האובייקט user
. ללא שימוש ב-optional chaining, יהיה עליכם לבצע בדיקות קיום מרובות, אבל עם optional chaining תוכלו לגשת בצורה בטוחה למאפיין עם פקודה אחת בלבד.
שימוש ב-Optional Chaining עם מערכים ופונקציות
Optional chaining ישים לא רק למאפייני אובייקטים, אלא גם לאלמנטים במערכים ולקריאות לפונקציות.
דוגמה עם מערכים:
1const users = [{ name: 'Alice' }, { name: 'Bob' }];
2
3// Accessing the non-existent third element
4const thirdUser = users[2]?.name;
5console.log(thirdUser); // undefined
דוגמה עם פונקציות:
1const user = {
2 greet: function() {
3 return 'Hello!';
4 }
5};
6
7// Call the function only if greet exists
8const greeting = user.greet?.();
9console.log(greeting); // Hello!
10
11// Return undefined if greet does not exist
12const nonExistentGreeting = user.nonExistentMethod?.();
13console.log(nonExistentGreeting); // undefined
שילוב Optional Chaining עם ערכי ברירת מחדל
כאשר משתמשים ב-optional chaining, נהוג להשתמש בלוגי OR (||
) או באופרטור nullish coalescing (??
) כדי להגדיר ערכי ברירת מחדל אם מאפיין לא קיים.
דוגמה:
1const user = {
2 name: 'John',
3 address: {
4 city: 'New York'
5 }
6};
7
8// Set a default value for a non-existent property
9const state = user?.address?.state || 'Unknown';
10console.log(state); // Unknown
11
12// Example using the nullish coalescing operator
13const zipCode = user?.address?.zipCode ?? '00000';
14console.log(zipCode); // 00000
האופרטור ||
מתייחס ל-false
, 0
, ''
וכו' כ-falsy, בעוד שהאופרטור ??
משתמש בערך ברירת המחדל רק אם האופרנד הוא null
או undefined
.
היתרונות של Optional Chaining
- גישה בטוחה לאובייקטים מקוננים: באמצעות optional chaining, אין צורך בבדיקות קיום מפורשות, מה שהופך את הקוד לתמציתי יותר.
- מניעת שגיאות: זה יכול למנוע שגיאות בזמן ריצה גם אם מאפיין הוא
null
אוundefined
. - קריאות ותחזוקה משופרות: במיוחד כאשר עובדים עם אובייקטים מקוננים רבים, הקריאות של הקוד משתפרת באופן משמעותי.
זהירות עם Optional Chaining
- שימוש תכוף ב-optional chaining עשוי להעיד שדגם מבנה הנתונים הוא מורכב מדי. עליכם לשאוף למודל נתונים פשוט.
- מכיוון שחלק מהדפדפנים הישנים ומנועי JavaScript לא תומכים בכך, ייתכן שתצטרכו להשתמש ב-polyfills או transpilers.
סיום
Optional chaining הוא פיצ'ר חזק שמפשט גישה בטוחה למאפיינים ולפונקציות של אובייקטים מקוננים ב-JavaScript. זה יעיל במיוחד כאשר ניגשים למבני נתונים מקוננים עמוקים, ומסייע במניעת שגיאות ובהשגת קריאות קוד משופרת.
תוכלו לעקוב אחר המאמר שלמעלה באמצעות Visual Studio Code בערוץ היוטיוב שלנו. נא לבדוק גם את ערוץ היוטיוב.