זהו נושא דיון מלווה לערך המקורי שב־https://www.tocode.co.il/bundles/frontend/lessons/js-class-syntax-lab
זהו נושא דיון מלווה לערך המקורי שב־https://www.tocode.co.il/bundles/frontend/lessons/js-class-syntax-lab
היי ינון לגבי תרגיל 1 השתמשתי בקלט prompt בשביל להחליף את השמות.
יש דרך אחרת לעשות את זה?
הי,
בתרגיל לא היה צריך לאפשר בחירת שם. כרגע prompt הוא דרך טובה, אבל בהמשך הקורס נלמד שיטות יותר טובות כדי לשלוט גם במראה הדיאלוג שנפתח
ינון שלום
סליחה על הקטונוניות
מדעה השמתמשת כאן ב
var winningCar = race.winner();
במקום let
הי,
אין מילה כזאת קטנוניות בקורסים - חשוב להבין את כל הפרטים.
אני מדבר על ההבדל בין var ל let ל const בשיעור כאן:
https://www.tocode.co.il/bundles/es6/lessons/let-and-const
בגדול בקוד חדש מומלץ תמיד לבחור בין let ל const בגלל התנהגות מוזרה של var במספר מקרי קצה. פה בתרגיל בגלל שזו תוכנית קטנה זה לא ממש משנה (זה היה var כנראה כי את הקטע הזה בתרגיל כתבתי מזמן). בכל מקרה שיניתי ל const שיהיה מסודר
היי
האם כך פחות או יותר התכוונת שנפתור את תרגיל 3?
class Race {
construct() {
this.cars = [];
}
addCars(c1,c2,c3) {
this.cars = [c1,c2,c3];
}
winner() {
let win_color;
let win_speed;
if (this.cars[0].isFasterThan(this.cars[1]) && this.cars[0].isFasterThan(this.cars[2])) {
win_color = this.cars[0].color;
win_speed = this.cars[0].speed;
}
else if (this.cars[1].isFasterThan(this.cars[0]) && this.cars[1].isFasterThan(this.cars[2])) {
win_color = this.cars[1].color;
win_speed = this.cars[1].speed;
}
else {
win_color = this.cars[2].color;
win_speed = this.cars[2].speed;
}
return {
color: win_color,
speed: win_speed,
}
}
}
הי,
כן זה עובד אבל שים לב לקוד שכתבת בפונקציה winner - יש את אותו בלוק שחוזר על עצמו כמה פעמים. רוצה לנסות להשתמש בלולאה כדי לכתוב גירסה יותר ממוקדת?
class Race {
constructor(){
this.cars = [];
}
addCars(cars){
cars.push(this.cars);
}
winner(){
let winColor;
let winSpeed;
for(i = 0; this.cars < this.cars.length; i++){
if(this.cars[i].isFasterThan(this.cars[i+1])){
winColor = this.cars[i].color;
winSpeed = this.cars[i].speed;
}
return {
color: winColor,
speed: winSpeed,
}
}
}
}
משום מה הכל עובד פיקס רק ההכרזה על המנצח לא מוצלחת אשמח לעזרה
הי עדי
יש פה כמה בעיות בפיתרון. הסוג הראשון של בעיות הן בעיות תחביר:
-
הפונקציה
addCars
צריכה לקבל שלוש מכוניות, אבל אצלך היא מקבלת רק פרמטר אחד. -
בלולאה צריך להגדיר let לפני המשתנה i, וצריך להשתמש במשתנה זה בשביל התנאי כלומר:
for (let i=0; i < this.cars.length; i++) {
סוג שני של בעיות קשורות למה התוכנית אמורה לעשות:
-
לא ברור למה הפונקציה
addCars
מפעילה אתpush
על אוביקט המכוניות שקיבלה, ומעבירה בתור פרמטר אתthis.cars
-
לא ברור למה ה
return
נמצא בתוך לולאת ה for בפונקציהwinner
ולא אחריה
ובעיה אחרונה היא יותר כמו מוקש לעתיד מאשר בעיה מיידית - ואני מתכוון לפקודת ה return:
return {
color: winColor,
speed: winSpeed,
}
ב JavaScript, כל אוביקט הוא ייחודי. אפשר להחזיק כמה ״מצביעים״ או קישורים שונים לאותו אוביקט, ושני אוביקטים שונים יכולים שיהיו להם את אותם מפתחות וערכים ועדיין יהיו שונים. לדוגמה הקוד הבא מדפיס true:
const x = { name: 'ynon' };
const y = x;
console.log(x === y);
אבל הקוד הבא מדפיס false:
const x = { name: 'ynon' };
const y = { name: x.name };
console.log(x === y);
בדוגמה השניה יש לנו שני אוביקטים שונים שבמקרה יש להם את אותם שדות עם אותם ערכים.
בפונקציה כמו winner אם נתקדם עם הפיתרון שלך, יהיה לנו מצב מוזר בו הפונקציה מחזירה אוביקט חדש עם אותם מפתחות וערכים. במקרה כזה נקבל false בכל אחת משלושת ההדפסות:
const x = race.winner();
console.log(x === c1); // false
console.log(x === c2); // false
console.log(x === c3); // false
כלומר קיבלתי מכונית ״מנצחת״ שבכלל לא היתה בין שלושת המכוניות שהשתתפו במירוץ, אלא שבמקרה היה לה את אותם צבע ומהירות כמו למכונית שניצחה.
הפיתרון לזה יהיה לבצע return למשהו מסוים מהמערך ולא ליצור אוביקט חדש בתוך הלולאה. למשל אם הלולאה תמצא את האינדקס של המכונית המהירה ביותר, אפשר יהיה להפעיל:
return this.cars[winnerIndex];
עוד אפשרות היא לשמור בצד לא את המאפיינים color ו speed אלא את המכונית עצמה, כלומר בתוך ה if לכתוב:
winCar = this.cars[i];
ואז להחזיר את winCar
בסוף הפונקציה.
<script>
class Car {
constructor(color, speed = 0) {
this.color = color;
this.speed = speed;
}
drive(speed) {
this.speed = speed;
}
isFasterThan(other) {
return this.speed > other.speed;
}
}
class Race {
constructor(){
this.c1 = "";
this.c2 = "";
this.c3 = "";
}
addCars(c1,c2,c3){
this.cars = [c1,c2,c3];
//this.speeds = [c1.speed,c2.speed,c3.speed]
}
winner()
{
//this.max = Math.max.apply(Math, this.speeds);
//console.log(this.max)
for(let i=0 ; i<this.cars.length; i++){
// console.log(this.cars[0])
if(this.cars[0].isFasterThan(this.cars[1]) && this.cars[0].isFasterThan(this.cars[2])){
return this.cars[0]
}
else if(this.cars[1].isFasterThan(this.cars[0]) && this.cars[1].isFasterThan(this.cars[2])){
return this.cars[1]
}
else if(this.cars[2].isFasterThan(this.cars[0]) && this.cars[2].isFasterThan(this.cars[1])){
return this.cars[2]
}
}
}
}
const c1 = new Car('red');
const c2 = new Car('blue', 50);
const c3 = new Car('black');
const race = new Race();
race.addCars(c1, c2, c3);
c1.drive(20);
c3.drive(10);
const winningCar = race.winner();
console.log('And the winner is: ' + winningCar.color);
ככה פתרתי האם זה בסדר ?
המחלקה של Car מצוינת
במחלקה של Race יש כמה דברים שהייתי משנה:
-
המירוץ תמיד ל-3 מכוניות. זה נכון שככה הופיע בדוגמת הקוד אבל אני לא רואה סיבה טובה שהקוד לא יסכים לעבוד על יותר או פחות מכוניות. בשביל לכתוב את הפונקציה addCars בצורה יותר גנרית אתה יכול לראות את הוידאו כאן:
קורס JavaScript ES 2022 שיעור פרמטרים לפונקציות -
אבל יותר מ
addCars
מה שמפריע פה זה הבנאי שמאתחל את שלושת המשתנים למחרוזת ריקה. בעיקרון אנחנו רוצים ששדה מידע במחלקה יכיל תמיד משהו מאותו ״טיפוס״. זה אומר שאם c1 צריך להחזיק מכונית אז זה הדבר היחיד שהוא יחזיק. לכן במקום משתנים עדיף לשמור שם מערך של מכוניות, וככה אתה לא מוגבל במספר המכוניות ולא צריך לשמור ערכים ״ריקים״ עד שיקראו ל addCars -
אחרי שעברנו למערך נוכל לעדכן גם את הפונקציה winner שתשתמש בלולאה וככה לקצר גם שם את הקוד.
נסה לעשות את השינויים ואחרי זה תדביק פה גירסה מתוקנת