ציין ב- JavaScript מוסבר על ידי בישול ארוחה פשוטה

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

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

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

לדוגמא, זהו משתנה גלובלי הנקרא מצב :

let state = "global";

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

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

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

מאמר זה מתאר את המצב בהקשר של React, ספריית JavaScript פופולרית.

אבל נחשו מה? אפילו מדינה יכולה לתת לך כאבי ראש ברגע שהקוד שלך מסתבך! שינוי מצב יכול לגרום לתוצאות לא מכוונות.

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

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

הדרכה זו תראה כיצד תוכלו לבשל ארוחה של ספגטי ורוטב מ- OOP ומנקודת מבט פונקציונלית.

הנה תצוגה מקדימה מהירה של שתי הגישות השונות:

בוא נקפוץ לזה. על מנת להבין מדריך זה, עליכם להבין פונקציות ואובייקטים ב- JavaScript.

שיטה מונחה עצמים (שימוש במדינה)

בתרשים שלמעלה הראינו שתי גישות שונות להכנת ארוחת פסטה זו:

  1. שיטה המתמקדת במצב הכלים השונים, כמו הכיריים, הסיר והפסטה.
  2. שיטה המתמקדת בהתקדמות המזון עצמו, ללא אזכור למצב הכלים האישיים (סירים, כיריים וכו ').

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

  1. גלובלי, או מצב הארוחה כולה.
  2. מקומי לכל אובייקט.

אנו הולכים להשתמש בתחביר ES6 במדריך זה ליצירת אובייקטים. הנה דוגמה למדינה גלובלית ולאב-טיפוס "פוט".

let stoveTemp = 500;
function Pot(){ this.boilStatus = ''; this.startBoiling = function(){ if( stoveTemp > 400) this.boilStatus = "boiling"; }}
let pastaPot = new Pot();pastaPot.startBoiling();
console.log(pastaPot);// Pot { boilStatus = 'boiling'; }

הערה: פשטתי את console.logההצהרה כדי להתמקד בעדכון המדינה.

הנה ייצוג חזותי של ההיגיון הזה:

לפני

לאחר

ישנם שני מצבים, וכאשר pastaPotנוצר באמצעות Potאב - טיפוס, בתחילה יש לו ריק boilStatus. אבל אז, יש שינוי במצב.

אנו רצים pastaPot.startBoiling(), ועכשיו boilStatus(המדינה המקומית) "רותחת", מכיוון שהמדינה העולמית stoveTempהיא מעל 400.

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

הנה הקוד שנוסיף לקטע הקוד לעיל:

function Pasta (){ this.cookedStatus = false; this.addToPot = function (boilStatus){ if(boilStatus == "boiling") this.cookedStatus = true; }}
let myMeal = new Pasta();myMeal.addToPot(pastaPot.boilStatus);
console.log(myMeal.cookedStatus);// true

וואה! זה הרבה בבת אחת. הנה מה שקרה.

  1. יצרנו אב טיפוס חדש של "פסטה", שבו לכל אובייקט תהיה מדינה מקומית שנקראת cookedStatus
  2. יצרנו מופע חדש של פסטה בשם myMeal
  3. השתמשנו המדינה מן pastaPotהאובייקט שיצרנו את הקטע האחרון כדי לקבוע אם אנחנו צריכים לעדכן את המצב הנקרא cookedStatusב myMealכדי מבושל.
  4. מכיוון שמצב ה- boilStatusin pastaPotהיה "רותח", הפסטה שלנו מבושלת כעת!

הנה התהליך הזה מבחינה ויזואלית:

לפני

לאחר

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

שיטה פונקציונלית (ללא מצב)

על מנת להבין את המצב באופן מלא, אתה אמור להיות מסוגל למצוא דרך להשיג את אותה התוצאה כמו הקוד לעיל מבלי לשנות את המצב בפועל. זה המקום שבו תכנות פונקציונלי עוזר!

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

אני לא הולך להעמיק יותר מדי בנושאים האלה, אבל אם אתה רוצה ללמוד עוד, אני ממליץ לך לבדוק את המדריך הזה לתכנות פונקציונלי ב- JavaScript.

Both of these principles discourage the use of state modification in your code. That means that we can’t use local or global state.

Functional programming instead encourages us to pass in parameters to individual functions. We can use outside variables, but we can’t use them as state.

Here’s an example of a function that will boil the pasta:

const stoveTemp = 500;
const cookPasta = (temp) => { if(temp > 400) return 'cooked';}
console.log(cookPasta(stoveTemp));// 'cooked'

This code will successfully return a string of ‘cooked’. But notice — there is no object that we are updating. The function simply returns the value that will be used in the next step.

Instead, we are focused on the inputs and outputs of one function: cookPasta.

This perspective looks at the transformation of the food itself, rather than the tools that are used to cook it. It’s a little harder to visualize, but we don’t need to have the function depend on external state.

Here’s what it looks like:

Think of it as a “timeline view” for the progress of the meal — this particular function just covers the first part, the transition from dry pasta to cooked pasta.

Now let’s cover the second part as the food is served. Here’s the code that will serve the meal. It will come after the code block above:

const serveMeal = (pasta) => { if (pasta == 'cooked') return 'Dinner is ready.'}
console.log( serveMeal(cookPasta(stoveTemp)) );// 'Dinner is ready.'

Now, we are delivering the results of the cookPasta function directly into the serveMeal function. Again, we are able to do this without changing state, or changing data structures.

Here’s a diagram that uses the “timeline view” to show how these two functions work together:

Interested In More Visual Tutorials?

If you enjoyed this guide, give it a “clap”!

And, if you would like to read more visual tutorials about HTML, CSS and JavaScript, check out the main CodeAnalogies site for 50+ tutorials.