הסמלים חדשים יחסית שכתוב ב-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
?
אילו מהקטגוריות הבאות מתארות סמלי 'ידוע'?