פעולות במחרוזות טקסט ותאריכים עם ECMAScript 6

הטמפלייטינג מגיע סוף סוף לג'אווהסקריפט ונילה.

אחד הדברים הכי יפים וגם לא מסובכים ב-ECMAScript 6 זו הדרך שבה אפשר לעבוד איתה בנוגע למחרוזות טקסט. בואו ונסתכל על הדוגמה:


var someName = 'Moshe',
    price = '20$';

var message = 'Hi ' +  someName + ', You owe me ' + price;
console.log(message); //"Hi Moshe, You owe me 20$"

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


var someName = 'Moshe',
    price = '20$';

var message = `Hi ${someName}, You owe me ${price}`;
console.log(message); //"Hi Moshe, You owe me 20$"

שימו לב למרכאות, לא מדובר במרכאות רגילות או כפולות אלא במרכאות מוטות `. אפשר להכניס לשם כל דבר, למשל אובייקטים מורכבים.


var customer = { name: "Foo" }
var card = { amount: 7, product: "Bar", unitprice: 42 }
var message = `Hello ${customer.name},
want to buy ${card.amount} ${card.product} for
a total of ${card.amount * card.unitprice} bucks?`

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


var someName = 'Moshe',
    price = 20;

var message = `Hi ${someName}, You owe me ${price + 30}`;
console.log(message); //"Hi Moshe, You owe me 50"

ואם זה מזכיר לכם את אנגולר (למשל) אתם לא טועים. בתוך הסוגריים המסולסלות אפשר להריץ את מה שרוצים.

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


function stringManipulation (strings, ...values) {
    console.log(strings[0]); //"foo\n"
    console.log(strings[1]); //"bar"
    console.log(strings.raw[0]); //"foo\\n"
    console.log(strings.raw[1]);  //"bar"
    console.log(values[0]); //42
    return 'someResult';
  
}
var myString = stringManipulation `foo\n${ 42 }bar`;
console.log(myString); //"someResult"

אז מה יש לנו כאן? יש לנו פונקציה מיוחדת שכאן קראתי לה stringManipulation אבל אפשר לקרוא לה באיזה שם שרוצים. אני מעביר אליה את הביטוי שלי (במקרה הזה foo\n${ 42 }bar ושימו לב שהוא עטוף במרכאות מיוחדות וגם שאני מעביר את מחרוזת הטקסט הזו בדרך שהיא מעט עקומה אבל הכרחית לפונקציות שמטפלות במחרוזות טקסט. את התוצאה שאני מקבל מהפונקציה אני מדפיס. במקרה הזה, כיוון שהפונקציה מחזירה לי someResult זה בדיוק מה שאקבל.

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

נכון שבהשוואה לגנרטורים, לפירוק מערכים ו for in מדובר במשהו פשוט יחסית שאפשר ליישם כבר היום?

הלאה – פונקציות i18n. למי שלא יודע מה זה, מדובר בקיצור של internationalization – בין ה-i ל-n יש 18 אותיות. בגדול מדובר בבינאום. למשל, באמריקה הרחוקה, כותבים את התאריך כשהחודש קודם. למשל, הראשון לספטמבר מצוין אצלם כך: 09/01. בניגוד לשאר העולם. במיון של אותיות, הטבטונים בני גרמניה ממיינים את ה-ä מייד אחרי a, בעוד שהויקינגים בני שוודיה ממיינים את ה-ä מיד אחרי ה-z ועוד שפע של טריקים ושטיקים כאלו שמדירים שינה מעיני מתכנתים מדורי דורות.

ECMAScript 6 מסייעת לסיפור הזה עם אובייקט intl. מי שיציץ בו ב-MDN יגלה שיש לו כמה תכונות מעניינות שיכולות לסייע במקרים של בינאום.

סדר מיון

באמצעות Intl.Collator אני יכול לקבוע סדר מיון שונה לרשימות. בעצם מדובר בפונקצית מיון מותאמת לשפה. בואו וניקח סצינה מהחיים. נניח שיש לי מערך שיש לו איברים בעברית ובאנגלית ואני נדרש למיינו. מן הסתם אני אשתמש ב-sort על המערך שלי. אבל למרבה הצער קודם הוא יציב את הערכים בעברית. אם אני השתמש ב-collator, המיון יתחשב בערכים בעברית קודם.

ככה זה נראה:


var array = [ "a", "b", "א" ]
var l10nHE = new Intl.Collator("he")

console.log(array.sort(l10nHE.compare)) // ["א", "a", "b"]
console.log(array.sort()) // ["a", "b", "א"]

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


var array = [ "ä", "a", "z" ]
var l10nDE = new Intl.Collator("de")
var l10nSV = new Intl.Collator("sv")

console.log(array.sort(l10nDE.compare)) // [ "a", "ä", "z" ]
console.log(array.sort(l10nSV.compare)) // [ "a", "z", "ä" ]

דוגמה נוספת ומגניבה היא המספרים. ברוב המקומות מקובל להציג מספרים עם פסיקים. למשל 1000 מוצג כ 1,000. חוץ מזה, יש עוד סיבוך – למשל כל מי שהתעסק באתרי מכירות לגרמנים יודע ששם הנקודה היא פסיק. לפני ES6, היינו צריכים קצת לירוק דם. פה זה ממש פשוט. אנחנו רק צריכים את קוד המדינה והשפה לפי ISO ואת אובייקט Intl. יוצרים NumberFormat עם קוד המדינה המתאים ואז אפשר לפרמט כל מספר לפי מה שאנחנו צריכים. רגע, לא מאמינים? הנה:


var l10nEN = new Intl.NumberFormat("en-US")
var l10nDE = new Intl.NumberFormat("de-DE")
console.log(l10nEN.format(1234567.89)); // "1,234,567.89"
console.log(l10nDE.format(1234567.89)); // "1.234.567,89"

אנחנו יכולים לשלב את דוגמת המספרים עם כסף (כן כן!) אם יש לנו את קוד המטבע של המדינה, אנחנו יכולים להדפיס גם את המחיר בפורמט המספר של המדינה. הנה דוגמה:


var l10nUSD = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })
var l10nGBP = new Intl.NumberFormat("en-GB", { style: "currency", currency: "GBP" })
var l10nEUR = new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" })
var l10nISR = new Intl.NumberFormat("he-IL", { style: "currency", currency: "ILS" })
console.log(l10nUSD.format(100200300.40)); // "$100,200,300.40"
console.log(l10nGBP.format(100200300.40)); // "£100,200,300.40"
console.log(l10nEUR.format(100200300.40)); //"100.200.300,40 €"
console.log(l10nISR.format(100200300.40)); //"100,200,300.40 ₪"

ואל תגידו שזה לא מגניב וגם פשוט.

נסיים עם התאריכים. יש מדינות… טוב, בארצות הברית מקובל להציג את החודש קודם ורק אז את היום. למה? למה?? רק האמריקאים ואלוהים יודעים ואני לא סגור על זה שהשם יתברך יודע בוודאות למה הם עובדים בפורמט העקום הזה. אבל זה מה יש ועם זה צריך לנצח. מה עושים? גם פה, Intl מציג יופי של אפשרויות לשינוי פורמט התאריך בדיוק באותו אופן שימו לב שה-format פה מקבל אובייקט Date ולא מחרוזת טקסט או מספר.


var l10nEN = new Intl.DateTimeFormat("en-US")
var l10nDE = new Intl.DateTimeFormat("de-DE")
var l10nHE = new Intl.DateTimeFormat("he-IL")
console.log(l10nEN.format(new Date("2015-12-02"))) //"12/2/2015"
console.log(l10nDE.format(new Date("2015-12-02"))) //"2.12.2015"
console.log(l10nHE.format(new Date("2015-12-02"))) //"2.12.2015"

וזה דבר מאוד מאוד שימושי.

פוסטים נוספים שכדאי לקרוא

פיתוח ב-JavaScript

Axios interceptors

תכנון נכון של קריאות AJAX באפליקציה ריאקטית וניהול השגיאות או ההצלחות עם פיצ׳ר נחמד של axios

פתרונות ומאמרים על פיתוח אינטרנט

יישום של nonce על מנת להגן מפני התקפות injection

בפוסט הקודם הסברתי על hash עם CSP על משאבי inline – שזה נחמד ומעולה אבל פחות ישים בעולם האמיתי שבו בדרך כלל התוכן ה-inline (בין

גלילה לראש העמוד