אוספים שנוספו לאינדקס

אוסף שנוסף לאינדקס הוא מבנה נתונים שבו רכיבים מאוחסנים וניגשים אליהם באמצעות אינדקסים ממוספרים. לערכים שמאוחסנים באוסף שנוסף לאינדקס מוקצים אינדקסים ממוספרים החל מ-0, דפוס שנקרא 'יצירת אינדקס אפס'. לאחר מכן אפשר לגשת לערכים שמאוחסנים באוסף שנוצר לאינדקס על ידי הפנייה לאינדקסים שלהם.

Array

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

יצירת מערך

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

תחביר מילולי של מערך משתמש בקבוצת סוגריים ([]) סביב אפס או יותר ערכי נתונים מופרדים בפסיקים:

const myArray = [];

התחביר של בונה המערך משתמש באובייקט Array המובנה של JavaScript כבונה עם מילת המפתח new:

const myArray = new Array();

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

const myArray = [ true, null, "String", false ];

myArray;
> [ true, null, "String", false ]

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

const myArray = new Array( true, null, "String", false );

myArray;
> Array(4) [ true, null, "String", false ]

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

// Firefox:\
const myArray = new Array( 10 );

myArray;
> Array(10) [ <10 empty slots> ]
// Chrome:
const myArray = new Array( 10 );

myArray;
> (10) [empty × 10]

מערכים שמכילים משבצות ריקות (שנקראים לפעמים 'מערכים sparse') הם מקרים מיוחדים. במקום להכיל ערך undefined או ערך null מפורש, משבצות ריקות בדרך כלל נחשבות לערכי undefined במקום אחר בשפה, אבל לא תמיד.

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

const myArray = [ true,, true, false ];

myArray;
> Array(4) [ true, <1 empty slot>, true, false ]

למרות שלא מתייחסים לכך כערך משמעותי בכל ההקשרים, חריץ ריק מובא בחשבון לאורך הכולל של המערך, מה שעלול להוביל לתוצאות לא צפויות כשחוזרים על ערכי המערך:

const myArray = [ 1,, 3, 4 ];

myArray.length;
> 4

for( const myValue of myArray ) {
  console.log( myValue + 10 );
}
> 11
> NaN
> 13
> 14

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

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

const arrayLiteral = [];
const arrayConstructor = new Array();

typeof arrayLiteral;
> "object"

arrayLiteral;
> Array []
    length: 0
    <prototype>: Array []

typeof arrayConstructor;
> "object"

arrayConstructor;
> Array []
    length: 0
    <prototype>: Array []

מכיוון ששתי התוצאות זהות, והתחביר המילולי של המערך תמציתי וליטרלי יותר, אנחנו ממליצים להשתמש תמיד בתחביר מילולי של מערך במקום בתחביר new Array().

גישה לערכי מערך

אפשר לגשת לרכיבים בודדים בתוך המערך באמצעות סימון סוגריים, קבוצה של סוגריים ([]) שמופיעים אחרי המערך או המזהה שלו, שמכיל מספר שמתייחס לאינדקס של הרכיב:


[ "My string", "My other string" ][ 1 ];
> "My other string"

const myArray = [ "My string", 50, true ];

myArray[ 0 ];
> "My string"

myArray[ 1 ];
> 50

myArray[ 2 ];
> true

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

const myArray = [ "My string", 50, true ];

myArray[ 2 ];
> true

myArray[ "2" ];
> true

ניסיון לגשת לרכיב מחוץ לאלמנטים שמוגדרים במערך יוביל ל-undefined, ולא לשגיאה:

const myArray = [ "My string", 50, true ];

myArray[ 9 ];
> undefined

משימת השמדה

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

השמדה של הקצאה משתמשת ברשימת מזהים דמוית מערך או אובייקט כדי לעקוב אחר ערכים. בצורתו הפשוטה ביותר, שנקראת binding pattern, הרס של כל ערך מהמערך או מהאובייקט, ומוקצה למשתנה תואם, שאותחל באמצעות let או const (או var):

const myArray = [ "A string", "A second string" ];
const [ myFirstElement, mySecondElement ] = myArray;

const myObject = { firstValue: false, secondValue: true };
const { myProp, mySecondProp } = myObject;

myFirstElement;
> "My string"

mySecondElement;
> "Second string"

myProp;
> false

mySecondProp;
> true

משתמשים בסוגריים מסולסלים ({}) כדי להשמיד אובייקט, ובסוגריים מרובעים ([]) כדי להשמיד מערך.

const myArray = [ false, true ];
const myObject = { firstValue: false, secondValue: true };

const [ myProp, mySecondProp ] = myObject;
> Uncaught TypeError: myObject is not iterable

const { myElement, mySecondElement } = myArray;

myElement
> undefined

mySecondElement;
> undefined

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

const myArray = [ 1, 2, 3 ];
const [ myElement, mySecondElement, myThirdElement ] = myArray;

myElement;
> 1

mySecondElement;
> 2

myThirdElement;
> 3

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

const myObject = { firstValue: 1, secondValue: 2, thirdValue 3 };
const { secondValue, thirdValue, firstValue } = myObject;

firstValue;
> 1

secondValue;
> 2

thirdValue;
> 3

ניתן לדלג על רכיבים על ידי השמטת מזהה:

const myArray = [ 1, 2, 3 ];
const [ firstValue,, secondValue ] = myArray;

firstValue;
> 1

secondValue;
> 3

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

const myArray = [ true, ];
const [ firstValue = "Default string.", secondValue = "Default string." ] = myArray;

firstValue;
> true

secondValue;
> "Default string."

בתהליך הבנייה לא מתבצעת אילוץ של ערכים לסוגים מסוימים. פירוש הדבר הוא שערכי "falsy", כמו מחרוזות ריקות ("") או null, עדיין נחשבים לערכים מוּפקים בעלי משמעות:

const myArray = [ false, null, 0, "",, undefined ];
const [ falseValue = true, nullValue = true, zeroValue = true, emptyStringValue = true, emptySlot = true, undefinedValue = true ] = myArray;

falseValue;
> false;

nullValue;
> null

zeroValue;
> 0

emptyStringValue;
> ""

emptySlot;
> true

undefinedValue;
> true

מפעיל הרחבה

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

const myArray = [ 1, 2, 3 ];

console.log( ...myArray );
> 1 2 3

תחביר המרווחים משמש בעיקר להעתקה ולשילוב של מערכים:

const myArray = [ 4, 5, 6 ];
const mySecondArray = [1, 2, 3, ...myArray ];

mySecondArray;
> Array(6) [ 1, 2, 3, 4, 5, 6 ]

ניתן להשתמש בתחביר ריווח רק בהקשרים הבאים:

על מערכים ומחרוזות, תחביר המרווחים חל רק כאשר צריכים להיות אפס ארגומנטים או יותר בקריאת פונקציה או רכיבים במערך. הדוגמה הראשונה לתחביר של אופרטור spread בקטע הזה פועלת כי היא מעבירה את ...myArray כארגומנט לשיטה console.log המובנית.

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

const myArray = [ 1, 2, 3 ];
const spreadVariable = ...myArray;
> Uncaught SyntaxError: Unexpected token '...'

אבל מעתיקים מערך על ידי פריסה של המערך המקורי בליטרל של מערך:

const myArray = [ 1, 2, 3 ];
const spreadArray = [ ...myArray ];

spreadArray;
> Array(3) [ 1, 2, 3 ]

כדי למזג את הרכיבים שמרכיבים שני מערכים או יותר למערך אחד:

const myArray = [ 1, 2, 3 ];
const mySecondArray = [ 4, 5, 6 ];
const myNewArray = [ ...myArray, ...mySecondArray ];

myNewArray;
> Array(6) [ 1, 2, 3, 4, 5, 6 ]

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

const myArray = [ true, false ];
const myFunction = ( myArgument, mySecondArgument ) => {
    console.log( myArgument, mySecondArgument );
};

myFunction( ...myArray );
> true false

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

const myObj = { myProperty : true };
const mySecondObj = { ...myObj };

mySecondObj;
> Object { myProperty: true }
const myFirstObj = { myProperty : true };
const mySecondObj = { additionalProperty : true };
const myMergedObj = { ...myFirstObj, ...mySecondObj };

myMergedObj;
> Object { myProperty: true, additionalProperty: true }

אופרטור ההתפשטות יוצר עותקים מסוג 'shallow'. המשמעות היא שהאובייקט לא מעתיק את אב הטיפוס של האובייקט המקורי ואת המאפיינים שלא ניתנים לספירה.

const myCustomPrototype = { protoProp: "My prototype." };
const myObj = Object.create( myCustomPrototype, {
    myEnumerableProp: {
        value: true,
        enumerable: true
    },
    myNonEnumerableProp: {
        value: false,
        enumerable: false
    }
});
const myNewObj = { ...myObj };

myObj;
> Object { myEnumerableProp: true, … }
    myEnumerableProp: true
    myNonEnumerableProp: false
    <prototype>: Object { protoProp: "My prototype." }

myNewObj;
> Object { myEnumerableProp: true }
    myEnumerableProp: true
    <prototype>: Object { … }

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

מפעילי מנוחה

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

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

const myArray = [ "First", "Second", "Third", "Fourth", "Fifth" ];

[ myFirstElement, mySecondElement, ...remainingElements ] = myArray;

myFirstElement;
> "First"

mySecondElement;
> "Second"

remainingElements;
> Array(3) [ "Third", "Fourth", "Fifth"]

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

function myFunction( ...myParameters ) {
    let result = 0;
    myParameters.forEach( ( myParam ) => {
        result += myParam;
    });
    return result;
};

myFunction( 2, 2 );
> 4

myFunction( 1, 1, 1, 10, 5 );
> 18

myFunction( 10, 11, 25 );
> 46

%TypedArray%

מערכים מוקלדים הם תכונה של ES6 שמיועדת לאחסן נתונים בינאריים מובְנים, לדוגמה כשעובדים עם קבצים שהועלו או עם WebGL.

כמו במקרה של סמלים, גם %TypedArray% הפונקציה הפנימית (שבדרך כלל מתועדת כ-%TypedArray% או @@TypedArray, כך שאי אפשר לחשוב שהיא נכס גלובלי) היא לא פונקציה בונה במובן הקונבנציונלי, ואי אפשר להפעיל אותה באמצעות new או לקרוא לה ישירות. במקום זאת, %TypedArray% מתייחס לסיווג-על של ההורה של בנאים נפרדים, שכל אחד מהם עובד עם פורמט נתונים בינארי ספציפי. מחלקת העל של ה-%TypedArray% המהותי מספקת מאפיינים ושיטות עזר שכל מחלקות המשנה של ה-constructor של %TypedArray% והמכונות שלהן מקבלות בירושה.

בחינת ההבנה

בהינתן 'const myArray = [ 30, 50, 70 ];' מה מחזיר 'myArray[1]'?

50
30
70

אם ל-'myArray' יש שלושה ערכים, מה מוחזר 'myArray[9]'?

Undefined
הודעת שגיאה
9
Null