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

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

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

יצירת מערך

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

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

const myArray = [];

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

const myArray = new Array();

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

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

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

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

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

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

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

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

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

myArray;
> (10) [empty × 10]

מערכים שמכילים חריצים ריקים (שנקראים לפעמים 'מערכים מועטים') הם מיוחדים במקרים שונים. במקום לכלול ערך 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. הימנעו משימוש במערכים מועטים בפיתוח מודרני.

בדומה לפרימיטיבים, ייצוג מילולי של מערך יורשת מאפיינים ושיטות מה-constructor שלה. מכיוון שמערך הוא צורה מיוחדת של אובייקט, תחביר מילולי של מערך התחביר של new Array() יוצר תוצאות זהות מבחינה פונקציונלית: אובייקט יורש את אב הטיפוס שלו מה-constructor של 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

בניית המטלה

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

בתהליך השמטת ההקצאה נעשה שימוש ברשימת מזהים דמוית מערך או אובייקט כדי לעקוב אחרי הערכים. בצורתו הפשוטה ביותר, נקראת דפוס קישור שהפעולה הזאת מופיעה, כל ערך פורק מהמערך או מהאובייקט ומוקצה ל משתנה תואם, שאותחל באמצעות 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 ]

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

עבור מערכים ומחרוזות, תחביר הפיזור חל רק כאשר אפס ארגומנטים או יותר בקריאה לפונקציה או לרכיבים במערך. הדוגמה הראשונה של התחביר של האופרטורים בקטע הזה פועל כי הוא מעביר את ...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 {  }

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

מפעיל מנוחה

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

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

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

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

myFirstElement;
> "First"

mySecondElement;
> "Second"

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

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

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 ולכן אי אפשר לחשוב עליו שמדובר בנכס גלובלי) הוא לא פונקציה של constructor בהיגיון הקונבנציונלי, ואי אפשר להפעיל אותו באמצעות new או להתקשר אליו ישירות. במקום זאת, המונח %TypedArray% מתייחס לסיווג-על הורה של אדם פרטי שכל אחד מהם פועל עם פורמט נתונים בינארי מסוים. מחלקת-על %TypedArray% מהותית מספקת מאפיינים ושיטות שירות כל מחלקות המשנה של %TypedArray% של הבנאים והמכונות שלהם יורשים אותן.

בדיקת ההבנה

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

70
50
30

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

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