المجموعات المفهرَسة

المجموعة المفهرسة هي بنية بيانات يتم فيها تخزين العناصر والوصول إليها باستخدام فهارس مرقّمة. إنّ القيم المخزّنة في مجموعة مُفهرَسة يتم تعيين فهارس مرقّمة لها بدءًا من 0، وهو نمط يُعرَف باسم "الفهرسة الصفرية". يمكنك بعد ذلك الوصول إلى القيم المخزنة في مجموعة مفهرسة من خلال الرجوع إلى فهارسها.

مصفوفة

الصفيف هو حاوية يمكن أن تحتوي على صفر أو أكثر من القيم من أي نوع بيانات، بما في ذلك الكائنات المعقدة أو المصفوفات الأخرى. يُطلق على القيم المخزنة في صفيف أحيانًا "عناصر" الصفيفة.

إنشاء صفيف

كما هو الحال مع أنواع البيانات الأولية، هناك طريقتان لإنشاء مصفوفة: إمّا كمصفوفة حرفية، أو عن طريق استدعاء دالة إنشاء 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]

المصفوفات التي تحتوي على خانات فارغة (تسمى أحيانًا "الصفائف المتفرقة") هي حالات خاصة. بدلاً من تضمين قيمة 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

إتلاف المهمة

إنّ تدمير المهمة هي طريقة مختصرة لاستخراج مجموعة من القيم من الصفائف أو الكائنات وتخصيصها لمجموعة من المُعرّفات، وهي عملية تُعرف أحيانًا باسم "تفريغ حزمة" بنية البيانات الأصلية، على الرغم من أنّها لا تعدِّل الصفيف أو العنصر الأصلي.

يستخدم الإتلاف قائمة معرفات تشبه مصفوفة أو كائن لتتبع القيم. في أبسط أشكالها، تُعرف باسم تدمير نمط الربط، يتم فك ضغط كل قيمة من الصفيف أو الكائن ويتم تعيينها إلى متغير مطابق، ويتم تهيئته باستخدام 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 }

ينشئ عامل الانتشار نسخ "ضحلة". وهذا يعني أنه لا ينسخ النموذج الأولي للكائن الأصلي والخصائص غير القابلة للتعداد.

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% الأساسية خصائص وطرق استخدام التي تكتسبها جميع الفئات الفرعية لأداة الإنشاء %TypedArray% ومثيلاتها.

التحقق من فهمك

ضع في الاعتبار `const myArray = [ 30, 50, 70 ];` ما الذي يعرضه `myArray[1]`؟

50
30
70

إذا كانت "myArray" تحتوي على ثلاث قيم، فما الذي تعرضه "myArray[9]`؟

Undefined
رسالة خطأ
9
Null