מחלקות

ES6 הציג את המושג 'כיתות' ב-JavaScript, ששונה קורסים בשפות תכנות אחרות. כאן המחלקות הן פונקציות מיוחדות משמשות כתבניות ליצירת אובייקטים שכבר מכילים נתונים, מאפיינים שמשויכים לנתונים האלה, ושיטות שקשורות למניפולציה של הנתונים האלה. האובייקטים, המאפיינים והשיטות האלה נקראים יחד 'חברים' של בכיתה.

כדי להגדיר כיתה, צריך להשתמש במילת המפתח class. בהתאם לשיטות המומלצות שנקבעה על ידי פונקציות ה-constructor המובנות של JavaScript, מתחילים מזהה מחלקה עם אות גדולה:

class MyClass {}

הכיתות נועדו לספק דרכים נגישות יותר לעבודה עם כלים מתקדמים של אב-טיפוס ופונקציות של בנאי:

class MyClass {}

typeof MyClass;
> "function"

כי הכיתות נוספו באופן חלקי כדי לעבוד עם JavaScript מתקדם לתכונות קלות ומושכות יותר, נקראות לפעמים "syntactic sugar". אבל, לפעמים אבל לא רק מספקים קיצורים שימושיים לעבודה עם ירושה של אב טיפוס. חדש: הזדמנויות שנוצרו על ידי תחביר לכיתה כדי לטפל בעיצוב ותיק ב-JavaScript בלי להציג בעיות תאימות לאחור. בתור אחד למשל, כל הקוד שבתוך הגוף של הכיתה תמיד מוערך מחמיר.

כדי ליצור מופע של מחלקה, צריך להשתמש באופרטור new.

class MyClass {}

const myClassInstance = new MyClass();

myClassInstance;
> Object { }

פונקציות שמוגדרות בתוך הגוף של המחלקה נחשפות כשיטות של כל מחלקה במחלקה הזו.

class MyClass {
    classMethod() {
        console.log( "My class method." );
    }
}

const myClassInstance = new MyClass();

myClassInstance.classMethod();
> "My class method."

שיטה שמוגדרת בתוך מחלקה הופכת לשיטה באב הטיפוס של במכונה עצמה. בגלל האופי של שרשרת אב טיפוס, ה-methods הבאות ישירות על האובייקט שמתקבל:

class MyClass {
  classMethod() {
    console.log( "My class method." );
  }
}

const myClassInstance = new MyClass( "A string." );

myClassInstance;
> Object { }
    <prototype>: Object { … }
        classMethod: function classMethod()
        constructor: class MyClass { constructor(myPassedValue) }
        <prototype>: Object { … }

myClassInstance.classMethod();
> "My class method."

יצירת מופע של מחלקה מפעילה את השיטה constructor() המיוחדת, מבצע כל 'הגדרה' שנדרשת למכונה החדשה שנוצרה, ומאתחל את כל המאפיינים שמשויכים אליו. כל הארגומנטים שמועברים לכיתה כשהערך כשנוצרת מכונה, היא זמינה ל-method constructor():

class MyClass {
  constructor( myPassedValue ) {
    console.log( myPassedValue );
  }
}

const myClassInstance = new MyClass( "A string." );
> "A string."

בגוף הכיתה, הערך של this מתייחס למכונה עצמה, עם מאפיינים שמוגדרים ב-this כמאפיינים של כל מופע של הסיווג הזה:

class MyClass {
  constructor( myPassedValue ) {
    this.instanceProperty = myPassedValue;
  }
}

const myClassInstance = new MyClass( "A string." );

myClassInstance;
> Object { instanceProperty: "A string." }

המאפיינים האלה זמינים גם לכל השיטות בגוף המחלקה:

class MyClass {
  constructor( myPassedValue ) {
    this.instanceProp = myPassedValue;
  }
  myMethod() {
    console.log( this.instanceProp );
  }
}

const myClassInstance = new MyClass( "A string." );

myClassInstance.myMethod();
> "A string."

אם לא מגדירים constructor() לכיתה, מנוע JavaScript מתבסס על 'ברירת מחדל' ריקה constructor. לכל כיתה יכול להיות רק פריט מיוחד אחד אמצעי בשם constructor():

class MyClass {
  constructor() {}
  constructor() {}
}
> Uncaught SyntaxError: A class may only have one constructor

אפשר להגדיר מחלקה באמצעות הצהרת כיתה או ביטוי מחלקה. הדוגמאות הקודמות היו הצהרות כיתתיות, שמחייבים הפעלה של שמות באמצעות new. אפשר לתת שמות לביטויים של הכיתה, נשאר ללא שם כדי ליצור בכיתה.

let ClassExpression = class {
    constructor() {}
};

ClassExpression;
> class  {}

אחד הדברים שבהם אפשר להשתמש בביטויי מחלקה אנונימיים הוא פונקציות ליצור מחלקות "בזמן אמת":

function classMaker() {
  return class {
    constructor() {}
  };
}

let MyVariable = classMaker();

MyVariable;
> class  {}

הצהרה מחדש על מחלקה באמצעות הצהרת מחלקה גורמת לשגיאת תחביר:


class MyClass {
    constructor( ) {
        console.log( "My class." );
    }
};

class MyClass {
    constructor() {
        console.log( "My new class." );
    }
};
> Uncaught SyntaxError: redeclaration of class MyClass

עם זאת, ביטויי מחלקה מאפשרים להגדיר מחדש מחלקה:

let ClassExpression = class MyClass { };

ClassExpression = class MyOtherClass {
    constructor( myString ) {
        this.myProp = myString;
    }
};

new ClassExpression( "String." );
> MyOtherClass {myProp: 'String.'}

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

let MyVariable = class MyClass {};

MyClass;
> Uncaught ReferenceError: MyClass is not defined

MyVariable;
> class MyClass {}

MyVariable.name;
> "MyClass"

כשמאתחלים משתנה באמצעות ביטוי מחלקה, הפונקציה הגדרת כללי העלאה של אחרי אותו משתנה צריך לבצע את הפעולות הנדרשות. ההצהרות לגבי הכיתה צריכות לעמוד בדרישות של אותו 'אזור מתים זמני' כללים כמו let ו-const, והם מתנהגים כאילו הם לא הורחבו אל החלק העליון של ההיקף הנוכחי שלהם, כלומר, הפעלת מחלקה לפני הצהרת הכיתה גורמת לשגיאה:

{
    let myVar = new MyClass( "Property string." );

    class MyClass {
        myProp;

        constructor( myString ) {
            this.myProp = myString;
        }
    };
};
> Uncaught ReferenceError: Cannot access 'MyClass' before initialization

בדיקת ההבנה

אילו מהאפשרויות הבאות מגדירות מחלקה בצורה נכונה?

class MyClass {}
myClass = class {}
new class()

כמה שיטות constructor() יכולות להיות לכיתה?

אחת
ללא
ללא הגבלה