סמל

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

String() === String()
> true

String( "My string." ) === String( "My string." );
> true

עם זאת, אסור ליצור שני סמלים באמצעות הפונקציה Symbol() שווה בהחלט:

Symbol() === Symbol()
> false

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

const mySymbol = Symbol( "Desc" );

const myObject = {

}

myObject
> Object { Symbol("Desc"): "propSymbol" }

קיימים שלושה סוגי סמלים:

  • סמלים שנוצרו באמצעות Symbol()
  • סמלים משותפים שהוגדרו ומאוחזרים ממרשם סמלים גלובלי באמצעות Symbol.for()
  • "סמלים ידועים" מוגדר כמאפיינים סטטיים באובייקט הסמל. הסמלים האלה מכילים שיטות פנימיות שאי אפשר להחליף בטעות.

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

Symbol( "My symbol." ) === Symbol( "My symbol." );
> false

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

let mySymbol = Symbol( "My symbol." );

mySymbol
.description
> "My symbol."

אבל לא ניתן ליצור סמל באמצעות מילת המפתח new:

let mySymbol = new Symbol();

> Uncaught TypeError: Symbol is not a constructor

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

סמלים משותפים

השיטה Symbol.for() מנסה לחפש סמלים קיימים מרשם סמלים גלובלי ברמת זמן הריצה, שהמפתח שלו הוא מחרוזת נתונה, והחזרת סימן תואם, אם נמצא. אם הוא לא נמצא, נוצר סמל עם המפתח שצוין ומוסיף אותו למרשם הגלובלי:

let sharedSymbol = Symbol.for( "My key." );

sharedSymbol
=== Symbol.for( "My key." )
> true

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

Symbol( "String" ) === Symbol( "String" );
> false

Symbol( "String" ) === Symbol().for( "String" );
> false

Symbol().for( "String" ) === Symbol().for( "String" );
> true

כדי לאחזר את המפתח של סמל כלשהו ממרשם הסמלים, משתמשים בפקודה Symbol.keyFor():

let mySymbol = Symbol.for( "Key." );

Symbol.keyFor( mySymbol ) ;
> "Key."

"ידוע" סמלים

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

Symbol;
> function Symbol()
    asyncIterator
: Symbol(Symbol.asyncIterator)
   
for: function for()
    hasInstance
: Symbol("Symbol.hasInstance")
    isConcatSpreadable
: Symbol("Symbol.isConcatSpreadable")
    iterator
: Symbol(Symbol.iterator)
    keyFor
: function keyFor()
    length
: 0
    match
: Symbol("Symbol.match")
    matchAll
: Symbol("Symbol.matchAll")
    name
: "Symbol"
    prototype
: Object { }
    replace
: Symbol("Symbol.replace")
    search
: Symbol("Symbol.search")
    species
: Symbol("Symbol.species")
    split
: Symbol("Symbol.split")
    toPrimitive
: Symbol("Symbol.toPrimitive")
    toStringTag
: Symbol("Symbol.toStringTag")
    unscopables
: Symbol("Symbol.unscopables")
   
<prototype>: function ()

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

פעמים רבות, ערכי סמלים ידועים מתאפיינים מסוג קידומת @@ או שתחומים ב-% עד להבדיל בין המפתחות שלהם לבין אבות הטיפוס שניתנים לשינוי. לדוגמה, @@match. (או %match%) הוא הפניה אל Symbol.match שלא ניתן לשינוי, ולא String.prototype.match

בדיקת ההבנה

האם אפשר ליצור סמל באמצעות new?

כן
לא

אילו מהקטגוריות הבאות מתארות סמלי 'ידוע'?

סמלים שאתם משתמשים בהם לעיתים קרובות
מאפיינים סטטיים של האובייקט 'Symbol'
מפתחות מאפיין ייחודיים לגישה ולשינוי של JavaScript שיטות מובנות