المأجورون لإنشاء مصفوفات JavaScript

نصائح مفيدة لإنشاء مصفوفات ونسخها في JavaScript.

أحد الجوانب المهمة جدًا لكل لغة برمجة هو أنواع البيانات والهياكل المتوفرة في اللغة. توفر معظم لغات البرمجة أنواع بيانات لتمثيل البيانات المعقدة والعمل معها. إذا كنت قد عملت مع لغات مثل بايثون أو روبي، يجب أن شهدت أنواع البيانات مثل القوائم ، مجموعات ، الصفوف ، التجزئة ، dicts ، وهلم جرا.

في جافا سكريبت، لا يوجد الكثير من أنواع البيانات المعقدة - لديك ببساطة المصفوفات و الأشياء . ومع ذلك، تم إضافة بضعة أنواع البيانات والهياكل في ES6 إلى اللغة، مثل حرف ، مجموعات ، و الخرائط .

المصفوفات في JavaScript هي كائنات عالية المستوى تشبه القائمة مع خاصية الطول وخصائص الأعداد الصحيحة كفهارس.

في هذه المقالة ، أشارك بعض الاختراقات لإنشاء مصفوفات جافا سكريبت جديدة أو استنساخ المصفوفات الموجودة بالفعل.

تكوين المصفوفات: منشئ المصفوفة

الطريقة الأكثر شيوعًا لإنشاء المصفوفات هي استخدام البنية الحرفية للصفيف ، وهي طريقة مباشرة جدًا. ومع ذلك ، عندما تريد إنشاء مصفوفات ديناميكيًا ، فقد لا تكون الصيغة الحرفية للصفيف هي الطريقة الأفضل دائمًا. طريقة بديلة هي استخدام Arrayالمنشئ.

فيما يلي مقتطف رمز بسيط يوضح استخدام Arrayالمنشئ.

من المقتطف السابق ، يمكننا أن نرى أن Arrayالمنشئ ينشئ مصفوفات بشكل مختلف اعتمادًا على الوسائط التي يتلقاها.

المصفوفات الجديدة: بطول محدد

لنلقِ نظرة عن كثب على ما يحدث عند إنشاء Arrayطول جديد. يقوم المُنشئ فقط بتعيين lengthخاصية المصفوفة على الطول المحدد ، دون ضبط المفاتيح.

من المقتطف أعلاه ، قد تميل إلى الاعتقاد بأن كل مفتاح في المصفوفة قد تم ضبطه على قيمة undefined. لكن الحقيقة هي أن هذه المفاتيح لم يتم ضبطها أبدًا (فهي غير موجودة).

يوضح الرسم التوضيحي التالي الأمر بشكل أوضح:

هذا يجعل من غير المجدي محاولة استخدام أي من طرق تكرار المصفوفات مثل map()، filter()أو reduce()معالجة المصفوفة. لنفترض أننا نريد ملء كل فهرس في المصفوفة بالرقم 5كقيمة. سنحاول ما يلي:

يمكننا أن نرى أن هذا map()لم ينجح هنا ، لأن خصائص الفهرس غير موجودة في المصفوفة - lengthالخاصية موجودة فقط .

دعونا نرى طرقًا مختلفة يمكننا من خلالها حل هذه المشكلة.

1. استخدام Array.prototype.fill ()

على fill()طريقة يملأ كل عناصر صفيف من مؤشر بداية لمؤشر نهاية بقيمة ثابتة. لم يتم تضمين فهرس النهاية. يمكنك معرفة المزيد عن fill()هنا.

لاحظ أن هذا fill()سيعمل فقط في المتصفحات التي تدعم ES6.

هنا توضيح بسيط:

هنا ، تمكنا من ملء جميع عناصر المصفوفة التي أنشأناها بـ 5. يمكنك تعيين أي قيمة ثابتة لفهارس مختلفة من المصفوفة باستخدام fill()الطريقة.

2. استخدام Array.from ()

على Array.from()طريقة يخلق جديد، المنسوخة الضحلة Arrayالمثال من مجموعة مثل أو iterable الكائن. يمكنك معرفة المزيد عن Array.from()هنا.

لاحظ أن هذا Array.from()سيعمل فقط في المتصفحات التي تدعم ES6.

هنا توضيح بسيط:

هنا ، لدينا الآن undefinedقيم حقيقية تم تعيينها لكل عنصر من عناصر المصفوفة باستخدام Array.from(). هذا يعني أنه يمكننا الآن المضي قدمًا واستخدام طرق مثل .map()وعلى .filter()المصفوفة ، نظرًا لوجود خصائص الفهرس الآن.

هناك شيء آخر جدير بالملاحظة Array.from()وهو أنه يمكن أن يأخذ متغيرًا ثانيًا ، وهو دالة الخريطة. سيتم استدعاؤه على كل عنصر من عناصر المصفوفة. هذا يجعلها دعوة زائدة عن الحاجة .map()بعد Array.from().

اليك مثال بسيط:

3. استخدام عامل الانتشار

في المشغل انتشار( ...) ، المضافة في ES6 ، يمكن استخدامها لنشر عناصر المصفوفة ، وضبط العناصر المفقودة على قيمة undefined. سينتج عن ذلك نفس النتيجة مثل استدعاء Array.from()المصفوفة فقط باعتبارها الوسيطة الوحيدة.

فيما يلي توضيح بسيط لاستخدام عامل الانتشار:

يمكنك المضي قدمًا واستخدام طرق مثل .map()وعلى .filter()المصفوفة ، نظرًا لوجود خصائص الفهرس الآن.

باستخدام Array.of ()

تمامًا كما رأينا عند إنشاء مصفوفات جديدة باستخدام Arrayالمُنشئ أو الوظيفة ، Array.of()يتصرف بطريقة مشابهة جدًا. في الواقع ، يتمثل الاختلاف الوحيد بين Array.of()و Arrayفي كيفية تعاملهم مع وسيطة عدد صحيح واحد تم تمريرها إليهم.

أثناء Array.of(5)إنشاء مصفوفة جديدة بعنصر واحد ، 5وخاصية طول 1، Array(5)ينشئ مصفوفة فارغة جديدة بها 5 فتحات فارغة وخاصية طول 5.

var array1 = Array.of(5); // [5] var array2 = Array(5); // Array(5) {length: 5}

إلى جانب هذا الاختلاف الكبير ، Array.of()يتصرف مثل Arrayالمنشئ تمامًا. يمكنك معرفة المزيد عن Array.of()هنا.

لاحظ أن هذا Array.of()سيعمل فقط في المتصفحات التي تدعم ES6.

التحويل إلى المصفوفات: أمثال المصفوفات والمتكررة

إذا كنت تكتب وظائف JavaScript لفترة كافية ، فيجب أن تعرف بالفعل عن argumentsالكائن - وهو كائن يشبه المصفوفة متاح في كل دالة للاحتفاظ بقائمة الوسائط التي تتلقاها الوظيفة. على الرغم من أن argumentsالكائن يشبه إلى حد كبير مصفوفة ، إلا أنه لا يمكنه الوصول إلى Array.prototypeالأساليب.

قبل ES6 ، سترى عادةً مقتطف رمز مثل ما يلي عند محاولة تحويل argumentsالكائن إلى مصفوفة:

باستخدام Array.from()أو معامل الانتشار ، يمكنك بسهولة تحويل أي كائن يشبه المصفوفة إلى مصفوفة. ومن ثم ، بدلاً من القيام بذلك:

var args = Array.prototype.slice.call(arguments);

يمكنك القيام بأي مما يلي:

// Using Array.from() var args = Array.from(arguments); // Using the Spread operator var args = [...arguments];

تنطبق هذه أيضًا على العناصر التكرارية كما هو موضح في الرسم التوضيحي التالي:

دراسة حالة: وظيفة المدى

كدراسة حالة قبل المتابعة ، سننشئ range()وظيفة بسيطة لتنفيذ اختراق المصفوفة الجديد الذي تعلمناه للتو. الوظيفة لديها التوقيع التالي:

range(start: number, end: number, step: number) => Array

هنا مقتطف شفرة:

في مقتطف الشفرة هذا ، استخدمنا Array.from()إنشاء مصفوفة النطاق الجديدة ذات الطول الديناميكي ثم نشرها بأرقام متزايدة بشكل تسلسلي من خلال توفير وظيفة تعيين.

لاحظ أن مقتطف الشفرة أعلاه لن يعمل مع المتصفحات التي لا تدعم ES6 إلا إذا كنت تستخدم polyfills.

فيما يلي بعض النتائج من استدعاء range()الوظيفة المحددة في مقتطف الشفرة أعلاه:

يمكنك الحصول على عرض رمز حي عن طريق تشغيل القلم التالي على Codepen :

صفائف الاستنساخ: التحدي

في JavaScript ، المصفوفات والكائنات هي أنواع مرجعية. هذا يعني أنه عندما يتم تعيين متغير أو مصفوفة أو كائن ، فإن ما يتم تعيينه للمتغير هو إشارة إلى الموقع في الذاكرة حيث تم تخزين المصفوفة أو الكائن.

المصفوفات ، مثل أي كائن آخر في JavaScript ، هي أنواع مرجعية. هذا يعني أن المصفوفات يتم نسخها حسب المرجع وليس بالقيمة.

تخزين أنواع المراجع بهذه الطريقة له العواقب التالية:

1. المصفوفات المتشابهة ليست متساوية.

هنا، ونحن نرى أنه على الرغم من array1و array2يحتوي على ما يبدو نفس المواصفات مجموعة، فهي ليست على قدم المساواة. هذا لأن الإشارة إلى كل من المصفوفات تشير إلى موقع مختلف في الذاكرة.

2. يتم نسخ المصفوفات بالإشارة وليس بالقيمة.

هنا ، نحاول النسخ array1إلى array2، لكن ما نقوم به أساسًا هو الإشارة array2إلى نفس الموقع في الذاكرة الذي array1يشير إليه. وبالتالي، على حد سواء array1، و array2أشر إلى نفس الموقع في الذاكرة وتكون على قدم المساواة.

المعنى الضمني لهذا هو أنه عندما نجري تغييرًا عن array2طريق إزالة العنصر الأخير ، يتم array1أيضًا إزالة العنصر الأخير من . هذا لأنه تم إجراء التغيير في الواقع إلى مجموعة المخزنة في الذاكرة، في حين array1و array2لا تعد سوى إلى ذلك الموقع نفسه في الذاكرة حيث يتم تخزين مجموعة.

صفائف الاستنساخ: المأجورون

1. استخدام Array.prototype.slice ()

و slice()الأسلوب بإنشاء نسخة الضحلة من جزء من مجموعة دون تعديل مجموعة. يمكنك معرفة المزيد عن slice()هنا.

الحيلة هي استدعاء slice()إما 0كوسيطة وحيدة أو بدون أي حجج على الإطلاق:

// with O as only argument array.slice(0); // without argument array.slice();

فيما يلي توضيح بسيط لاستنساخ مصفوفة باستخدام slice():

هنا ، يمكنك أن ترى أنه array2نسخة من array1نفس العناصر والطول. ومع ذلك ، فإنها تشير إلى مواقع مختلفة في الذاكرة ، ونتيجة لذلك فهي ليست متساوية. تلاحظ أيضًا أنه عندما نجري تغييرًا على array2عن طريق إزالة العنصر الأخير ، array1يظل الأمر دون تغيير.

2. استخدام Array.prototype.concat ()

تُستخدم concat()الطريقة لدمج مصفوفتين أو أكثر ، مما ينتج عنه مصفوفة جديدة ، بينما تُترك المصفوفات الأصلية بدون تغيير. يمكنك معرفة المزيد عن concat()هنا.

الحيلة هي استدعاء concat()إما بمصفوفة فارغة ( []) كوسيطة أو بدون أي وسيطات على الإطلاق:

// with an empty array array.concat([]); // without argument array.concat();

concat()يشبه استنساخ المصفوفة استخدام slice(). فيما يلي توضيح بسيط لاستنساخ مصفوفة باستخدام concat():

3. استخدام Array.from ()

كما رأينا سابقًا ، Array.from()يمكن استخدامه لإنشاء مصفوفة جديدة وهي نسخة ضحلة من المصفوفة الأصلية. هنا توضيح بسيط:

4. استخدام Array Destructing

مع ES6، لدينا بعض أدوات أكثر قوة في مربع الأدوات لدينا مثل الإتلاف ، انتشارالمشغل ، السهم وظائف ، وهلم جرا. يعد التدمير أداة قوية للغاية لاستخراج البيانات من أنواع معقدة مثل المصفوفات والكائنات.

الحيلة هي استخدام تقنية تسمى معلمات الراحة ، والتي تتضمن مزيجًا من إتلاف المصفوفة وعامل الانتشار كما هو موضح في المقتطف التالي:

let [...arrayClone] = originalArray;

ينشئ المقتطف أعلاه متغيرًا مسمى arrayCloneوهو نسخة من originalArray. فيما يلي توضيح بسيط لاستنساخ مصفوفة باستخدام إتلاف المصفوفة:

الاستنساخ: الضحلة مقابل العميقة

جميع تقنيات استنساخ المصفوفات التي اكتشفناها حتى الآن تنتج نسخة ضحلة من المصفوفة. لن تكون هذه مشكلة إذا كانت المصفوفة تحتوي على قيم أولية فقط. ومع ذلك ، إذا كانت المصفوفة تحتوي على مراجع كائنات متداخلة ، فستظل تلك المراجع كما هي حتى عند نسخ المصفوفة.

هذا توضيح بسيط للغاية لهذا:

لاحظ أن تعديل المصفوفة المتداخلة قد أدى array1أيضًا إلى تعديل المصفوفة المتداخلة array2والعكس صحيح.

يكمن حل هذه المشكلة في إنشاء نسخة عميقة من المصفوفة وهناك طريقتان للقيام بذلك.

1. تقنية JSON

أسهل طريقة لإنشاء نسخة عميقة من المصفوفة هي استخدام مزيج من JSON.stringify()و JSON.parse().

JSON.stringify()يحول قيمة JavaScript إلى سلسلة JSON صالحة ، بينما JSON.parse()يحول سلسلة JSON إلى قيمة أو كائن JavaScript مطابق.

اليك مثال بسيط:

تقنية JSON بها بعض العيوب خاصةً عند تضمين قيم أخرى غير السلاسل والأرقام والمنطقية.

يمكن أن تُعزى هذه العيوب في تقنية JSON بشكل رئيسي إلى الطريقة التي JSON.stringify()تحول بها الطريقة القيم إلى سلسلة JSON.

فيما يلي توضيح بسيط لهذا الخلل في محاولة JSON.stringify()قيمة تحتوي على وظيفة متداخلة.

2. مساعد النسخ العميق

سيكون البديل القابل للتطبيق لتقنية JSON هو تنفيذ وظيفة مساعد النسخ العميق الخاصة بك لاستنساخ أنواع المراجع سواء كانت مصفوفات أو كائنات.

فيما يلي وظيفة نسخ عميقة بسيطة للغاية ومبسطة تسمى deepClone:

الآن هذه ليست أفضل وظائف النسخ العميق الموجودة هناك ، كما سترى قريبًا مع بعض مكتبات JavaScript - ومع ذلك ، فهي تؤدي نسخًا عميقة إلى حد كبير.

3. استخدام مكتبات JavaScript

وظيفة مساعد النسخة العميقة التي حددناها للتو ليست قوية بما يكفي في استنساخ جميع أنواع بيانات JavaScript التي قد تكون متداخلة داخل كائنات أو مصفوفات معقدة.

توفر مكتبات JavaScript مثل Lodash و jQuery وظائف مساعدة للنسخ العميق أكثر قوة مع دعم لأنواع مختلفة من بيانات JavaScript.

فيما يلي مثال يستخدم _.cloneDeep()من مكتبة Lodash:

إليك نفس المثال ولكن باستخدام $.extend()مكتبة jQuery:

استنتاج

في هذه المقالة ، تمكنا من استكشاف العديد من التقنيات لإنشاء مصفوفات جديدة ديناميكيًا واستنساخ المصفوفات الموجودة بالفعل ، بما في ذلك تحويل الكائنات التي تشبه المصفوفة والمتكررة إلى مصفوفات.

لقد رأينا أيضًا كيف يمكن لبعض الميزات والتحسينات الجديدة التي تم إدخالها في ES6 أن تمكننا من أداء بعض التلاعبات بشكل فعال على المصفوفات.

استخدمنا ميزات مثل التدمير وعامل الانتشار لاستنساخ المصفوفات ونشرها. يمكنك معرفة المزيد حول التدمير من هذه المقالة.

التصفيق والمتابعة

إذا وجدت هذه المقالة ثاقبة ، فأنت حر في إعطاء بعض جولات التصفيق إذا كنت لا تمانع.

يمكنك أيضًا متابعتي على Medium (Glad Chinda) لمزيد من المقالات الثاقبة التي قد تجدها مفيدة. يمكنك أيضًا متابعتي على Twitter (gladchinda).

نتمنى لك تجربة قرصنة سعيدة ...