אני ממש מצטער על הכותרת הצ'יזית וה'הו-כה-מתוחכמת', אבל לא יכולתי לעמוד בפיתוי. אחד הדברים היפים ב-ECMAScript 6 הוא הטיפול המקיף ב-class. למי שלא יודע, JavaScript היא לא ממש שפה מונחית עצמים אלא שפה מבוססת פרוטוטייפ. דבר שהקשה מעט על מימוש של עצמים. למרות שלא מעט מתכנתים אכן כתבו, או ניסו לכתוב קלאסים ויצא לכולנו קצת עקום. וכשאני אומר עקום אני מתכוון למשהו כזה:
"use strict";
function Book(title) {
this.title = title; //Public property.
var isCurrentlyReading = false; //Private property.
this.start = function() { //Privileged method .
this.isCurrentlyReading = true;
return this.isCurrentlyReading;
};
}
Book.prototype.stop = function stop() { //Define public method by prototype.
this.isCurrentlyReading = false;
};
var theShining = new Book('The Shining'); //Instance of the object.
console.log(theShining.title); //Return "The Shining".
var result = theShining.start();
console.log(result); //Return true.
See the Pen ECMAScript 5 Class by Ran Bar-Zik (@barzik) on CodePen.
מה יש לנו בעצם? הגדרת קלאס ששמו הוא Book ובו יש את כל מה שאנחנו מצפים בקלאס – יש לנו תכונות ויש לנו מתודות. יש לנו תכונות פומביות ויש לנו תכונות פרטיות. יש לנו מתודות פרטיות ופומביות וגם Privileged, כלומר כאלו שיכולות לגשת לתכונות פרטיות.
אבל מה? זה ברדק. ברדק להגדיר את זה, ברדק להבין את זה. ב-ECMAScript 6 מאוד קל להגדיר קלאס. אבל ממש. שימו לב:
"use strict";
class Book {
constructor(title) {
this.title = title;
this.isCurrentlyReading = false;
}
start() { //Public method.
this.isCurrentlyReading = true;
return this.isCurrentlyReading;
}
stop() { //Public property.
this.isCurrentlyReading = false;
}
}
var theShining = new Book('The Shining'); //Instance of the object.
console.log(theShining.title); //Return "The Shining".
var result = theShining.start();
console.log(result); //Return true.
אני לא חושב שאפשר להסביר יותר. אחת החולשות הגדולות כאן שאין פה private.
גם ירושה היא אפשרית עם הסינטקס הזה. גם בעבר היה אפשר לעשות ירושה, אבל זה היה כל כך נורא שבפועל בקושי השתמשו בזה בחיים האמיתיים. עם ECMAScript 6 לא צריך להתאמץ יתר על המידה. שימו לב איזה יופי:
"use strict";
class Book {
constructor(title) {
this.title = title;
this.isCurrentlyReading = false;
}
start() { //Public method.
this.isCurrentlyReading = true;
return this.isCurrentlyReading;
}
stop() { //Public property.
this.isCurrentlyReading = false;
}
}
class HorrorBook extends Book {
scream() { //Public method.
this.scream = true;
return this.scream;
}
}
var theShining = new HorrorBook('The Shining'); //Instance of the object.
console.log(theShining.scream()); //Return true.
console.log(theShining.title); //Return "The Shining".
See the Pen ECMAScript 6 – Class – inheritance by Ran Bar-Zik (@barzik) on CodePen.
ממש כמו בשפות אמיתיות, אנחנו יכולים להשתמש ב-super על מנת לקרוא למתודות של ההורה. הנה דוגמה:
"use strict";
class Book {
constructor(title) {
this.title = title;
this.isCurrentlyReading = false;
}
start() { //Public method.
this.isCurrentlyReading = true;
console.log('Start in base class.')
return this.isCurrentlyReading;
}
stop() { //Public property.
this.isCurrentlyReading = false;
}
}
class HorrorBook extends Book {
scream() { //Public method.
this.scream = true;
super.start(); //Will call to parent start.
return this.scream;
}
}
var theShining = new HorrorBook('The Shining'); //Instance of the object.
console.log(theShining.scream()); //Print start in base class and then true.
console.log(theShining.title); //Return "The Shining".
הנה, תראו בעצמכם:
See the Pen ECMAScript 6 – Class – inheritance + super by Ran Bar-Zik (@barzik) on CodePen.
בנוסף, אנחנו יכולים להכריז על תכונות סטטיות – כלומר כאלו שמשתמשים בהן ללא instance של האובייקט (זה ה-new) :
"use strict";
class Book {
constructor(title) {
this.title = title;
this.isCurrentlyReading = false;
}
start() { //Public method.
this.isCurrentlyReading = true;
console.log('Start in base class.')
return this.isCurrentlyReading;
}
stop() { //Public property.
this.isCurrentlyReading = false;
}
static throw() { //Static public method.
console.log('Throw it!');
}
}
Book.throw(); //Look ma! without instance.
See the Pen ECMAScript 6 – Class -static by Ran Bar-Zik (@barzik) on CodePen.
חושבים שזה הכל? יש גם set ו-get לתכונות של הקלאס. המתודות המיוחדות האלו מאפשרות לנו לעשות ולידציות/שינויים בכל השמה של משתנים. הנה דוגמה:
// ES6 get and set
class Person {
constructor(name) {
this._name = name;
}
get name() {
return this._name.toUpperCase();
}
set name(newName) {
this._name = newName; // Validation could be checked here such as only allowing non numerical values.
}
walk() {
console.log(this._name + ' is walking.');
}
}
let bob = new Person('Bob');
console.log(bob.name); // Outputs 'BOB', because it is running throught get.
אני יודע שזה המון דוגמאות, אבל בגדול, אין כאן שום דבר חדש. הכל היה אפשרי עם הגרסה הקודמת של ECMAScript, אבל עם ECMAScript 6 זה נראה הרבה יותר טוב וקריא. אין כאן משהו שהוא מעבר לסידור מחדש. שום יכולות חדשות, אבל ללא ספק הרבה יותר נוח ככה. במאמר המשך, אנסה להראות איך זה עובד עם שרשרת הפרוטוטייפ מאחורי הקלעים. אבל זה לא חיוני ללימוד ראשוני.
תגובה אחת
הי רן,
תודה על המאמר המעולה.
לגבי מתודות לא חשופות (פרייוט) אפשר לעשות את זה דרך טייפסקריבט, אבל זה רק משפיע על העורך לא יותר 🙂 אתה יכול לקרוא לפונקציה פרייוט וזה יעבוד אבל העורך יציג לך הודעה שהפונקציה לא נמצאה.
כייף לכנס לטייפסקריפט לפרויקטים גדולים ושלבי המעבר הם פשוט קלים! וכל הפריימוורקים הגדולים עוברים לתייפים, כמו אנגולר2, וריאקט (עם flowjs) וזה מה שחסר הגאפאסקריפט