♥♥ راسلنا لوضع اعلانك او من خلال شراء خدماتنا من خمسات وستحصل على مميزات اعلانية خيالية ♥♥
♥♥ ادعوا اصدقائك للاشتراك معنا لتصل جميع اعلانات التوظيف واخر الاخبار والمواضيع الى بريدكم الالكترونى مباشرة ♥♥
♥♥ ضع إعلانك معنا مجانا * وبدون تسجيل * ( نحقق لك الاشهار والانتشار وزيادة الاعضاء والزوار لدينا باك لينك عالي وارشفة عالية ومشاركات عبر التواصل الاجتماعي ) ♥♥
♥♥ ( لمتابعة آخر الاعلانات والوظائف والمواضيع والاخبار أولا بأول يرجى مراجعة موقعنا من كل حين لآخر حيث يتم النشر وبشكل مستمر لكافة المواضيع المتنوعة والهامة ) ♥♥
* منتديات هندسة بلا حدود * يتم تفعيل الحساب خلال 24 ساعة من قبل ادارة المنتدى او من خلال ايميل تسجيل العضو مباشرة *
في جافاسكربت، الكائنات والمصفوفات هي أكثر بنى البيانات المستعملة. تُتيح لنا الكائنات إنشاء كيان واحد يُخزّن عناصر البيانات حسب مفاتيحها، وتُتيح لنا المصفوفات بجمع مختلف عناصر البيانات في تجميعة مرتّبة (ordered collection).
ولكن حين نُمرّرها هذه الكائنات والمصفوفات إلى دالة، غالبًا ما لا نريد كامل الكائن/المصفوفة، بل بعضًا منها لا أكثر.
صياغة الإسناد بالتفكيك (Destructuring assignment) هي صياغة خاصّة تُتيح لنا ”فكّ“ المصفوفات أو الكائنات إلى مجموعة من المتغيرات إذ تكون أحيانًا أكثر منطقية. يفيدنا التفكيك أيضًا مع الدوال المعقّدة التي تحتوي على مُعاملات كثيرة وقيم مبدئية وغيرها وغيرها.
تفكيك المصفوفات إليك مثال عن تفكيك مصفوفة إلى مجموعة من المتغيرات:
// معنا مصفوفة فيها اسم الشخص واسم عائلته let arr = ["Ilya", "Kantor"]
alert(firstName); // Ilya alert(surname); // Kantor يمكننا الآن العمل مع تلك المتغيرات عوض عناصر المصفوفة. وما إن تجمع تابِع split وغيرها من توابِع تُعيد مصفوفات، سترى بريق هذا التفكيك يتألق:
let [firstName, surname] = "Ilya Kantor".split(' '); ”التفكيك“ (Destructuring) لا يعني ”التكسير“ (destructive)
نُسمّيه "الإسناد بالتفكيك" (destructuring assignment) لأنّه "يفكّك" العناصر بنسخها إلى متغيرات. أمّا المصفوفة نفسها فتبقى دون تعديل.
كتابة هذه الشيفرة أسهل من تلك الطويلة (ندعها لك تتخيّلها):
// let [firstName, surname] = arr; let firstName = arr[0]; let surname = arr[1]; أهمِل العناصر باستعمال الفواصل يمكنك ”رمي“ وتجاهل العناصر التي لا تريدها بإضافة فاصلة أخرى:
// لا نريد العنصر الثاني let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
alert( title ); // Consul في الشيفرة هذه تخطّينا العنصر الثاني في المصفوفة وأسندنا الثالث إلى المتغير title، كما وتخطّينا أيضًا باقي عناصر المصفوفة (ما من متغيّرات لها).
تعمل الميزة مع المُتعدَّدات حين تكون على اليمين
…الواقع هو أنّنا نستطيع استعمالها مع أيّ مُكرَّر وليس المصفوفات فقط:
let [a, b, c] = "abc"; // ["a", "b", "c"] let [one, two, three] = new Set([1, 2, 3]); أسنِدها إلى ما تريد على اليسار
يمكن أن نستعمل أيّ متغيّر يمكن إسناده على الجانب الأيسر من سطر الإسناد. لاحظ مثلًا إسناد خاصية لكائن:
let user = {}; [user.name, user.surname] = "Ilya Kantor".split(' ');
alert(user.name); // Ilya المرور على العناصر عبر .entries()
رأينا في الفصل الماضي التابِع Object.entries(obj). يمكننا استعماله مع التفكيك للمرور على مفاتيح الكائنات وقيمها:
let user = { name: "John", age: 30 };
// نمرّ على المفاتيح والقيم for (let [key, value] of Object.entries(user)) { alert(`${key}:${value}`); // name:John, then age:30 } …وذات الأمر للخارطة:
let user = new Map(); user.set("name", "John"); user.set("age", "30");
for (let [key, value] of user) { alert(`${key}:${value}`); // name:John, then age:30 } الباقي ”…“ لو أردنا أخذ القيم الأولى إضافةً إلى كل ما يليها، فنُضيف مُعاملًا آخر يجلب ”الباقي“ باستعمال ثلاث نقاط "...":
let [name1, name2, ...rest] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
alert(name1); // Julius alert(name2); // Caesar
// انتبه أنّ المتغير rest مصفوفة. alert(rest[0]); // Consul alert(rest[1]); // of the Roman Republic alert(rest.length); // 2 ستكون قيمة المتغير rest مصفوفةً فيها عناصر الباقية في المصفوفة الأولى. يمكننا استعمال أيّ اسم آخر بدل rest، المهم أن يكون قبله ثلاث نقاط ويكون الأخير في جملة الإسناد بالتفكيك.
القيم المبدئية لو كانت القيم في المصفوفة أقلّ من تلك في جملة الإسناد فلن يحدث أيّ خطأ. يُعدّ المحرّك القيم ”الغائبة“ غير معرّفة:
let [firstName, surname] = [];
alert(firstName); // undefined alert(surname); // undefined لو أردنا قيمة مبدئية تعوّض تلك الناقصة فيمكننا تقديمها باستعمال =:
alert(name); // Julius (من المصفوفة) alert(surname); // Anonymous (المبدئي) يمكن أن تكون القيم المبدئية تعابيرَ معقّدة أو استدعاءات دوال حتّى. لن يقدّر ناتجها المحرّك إلّا لو لم تمرّر القيم تلك. فمثلًا يمكننا استعمال الدالة promot لأخذ قيمتين مبدئيتين. أمّا هنا فستسأل عن القيمة الناقصة فقط:
// لا تطلب إلا اسم العائلة surname let [name = prompt('name?'), surname = prompt('surname?')] = ["Julius"];
alert(name); // Julius (نأخذه من المصفوفة) alert(surname); // نحترم هنا ما يقول promot تكفيك الكائنات الإسناد بالتفكيك يدعم أيضًا الكائنات. هذه صياغته الأساس:
let {var1, var2} = {var1:…, var2:…} على اليمين الكائن الموجود والذي نريد تقسيمه على عدّة متغيرات، وعلى اليسار نضع ”نمط“ الخاصيات المقابِلة له. لو كان الكائن بسيطًا، فهذا النمط هو قائمة باسم المتغيرات داخل {...}. مثال:
alert(title); // Menu alert(width); // 100 alert(height); // 200 تُسند الخاصيات options.title وoptions.width وoptions.height إلى المتغيرات المقابِلة لها. كما وأنّ الترتيب غير مهم: يمكنك فعل هذا أيضًا:
// غيّرنا الترتيب داخل let {...} let {height, width, title} = { title: "Menu", height: 200, width: 100 } يمكن أن يكون النمط على اليسار معقّدًا أكثر ومُحدّدًا فيحدّد طريقة ترابط الخاصيات بالمتغيرات عبر الخارطة (mapping).
لو أردنا إسناد خاصية إلى متغير له اسم آخر فعلينا استعمال النقطتين الرأسيتين لذلك (مثلًا options.width يصير في المتغير w):
alert(title); // Menu alert(w); // 100 alert(h); // 200 تعني النقطتان الرأسيتان ”هذا : يصير هذا“. في المثال أعلاه، تصير الخاصية width بالاسم w، والخاصية height بالاسم h والخاصية title كما هي title.
يمكننا هنا أيضًا وضع قيمة مبدئية للخاصيات الناقصة باستعمال "=" هكذا:
let options = { title: "Menu" };
let {width = 100, height = 200, title} = options;
alert(title); // Menu alert(width); // 100 alert(height); // 200 كما يمكن أن تكون هذه القيم المبدئية أيّة تعابير أو استدعاءات دوال كما مقابلاتها في المصفوفات ومُعاملات الدوال، ولن يقدّر المحرّك قيمتها إلّا لو لم تقدّم قيمة للدالة.
في الشيفرة أدناه، تطلب الدالة promot قيمة width ولا تطلب قيمة title:
let options = { title: "Menu" };
*!* let {width = prompt("width?"), title = prompt("title?")} = options; */!*
alert(title); // Menu alert(width); // (promot هنا نحترم أيضًا ما يقول) يمكننا أيضًا جمع النقطتان الرأسيتان والقيم المبدئية:
let options = { title: "Menu" };
let {width: w = 100, height: h = 200, title} = options;
alert(title); // Menu alert(w); // 100 alert(h); // 200 لو كان لدينا كائنًا معقّدًا فيه خاصيات كثيرة، فيمكننا استخراج ما نريد منه فقط:
// استخرج العنوان title ليكون متغيرًا هو فقط let { title } = options;
alert(title); // Menu نمط الباقي ”…“ ماذا لو كان للكائن خاصيات أكثر من المتغيرات التي لدينا؟ هل يمكننا أخذها وإسنادها في متغيّر ”rest“ أيضًا؟
أجل يمكننا استعمال نمط الباقي تمامًا مثل المصفوفات. بعض المتصفحات القديمة لا تدعمه (مثل إنترنت إكسبلورر، استعمل Babel لترقيعه polyfill، أي لتعويض نقص الدعم)، إلّا أن الحديثة تدعمه.
// title = خاصية بالاسم title // rest = كائن فيه باقي الخاصيات let {title, ...rest} = options;
// صار الآن title="Menu", rest={height: 200, width: 100} alert(rest.height); // 200 alert(rest.width); // 100 انتبه لو لم تضع let في المثال أعلاه، صرّحنا عن المتغيرات على يمين جملة الإسناد: let {…} = {…}. يمكننا طبعًا استعمال متغيرات موجودة دون let، ولكن هناك أمر، فهذا لن يعمل:
let title, width, height;
// سترى خطأ في هذا السطر {title, width, height} = {title: "Menu", width: 200, height: 100}; المشكلة هي أنّ جافاسكربت تتعامل مع {...} في سياق الشيفرة الأساس (أي ليس داخل تعبير آخر) على أنّها بنية شيفرة (Code Block). يمكن استعمال بنى الشيفرة هذه لجمع التعليمات البرمجية، هكذا:
{ // بنية شيفرة let message = "Hello"; // ... alert( message ); } وهنا يظنّ محرّك جافاسكربت بأنّ هذه بنية شيفرة فيعطينا الخطأ أعلاه، بينما ما نريد هو التفكيك. ولنقول للمحرّك بأنّ هذه ليست بنية شيفرة، نضع التعبير بين قوسين (...):
let title, width, height;
// الآن جيد ({title, width, height} = {title: "Menu", width: 200, height: 100});
alert( title ); // Menu تفكيك المتغيرات المتداخلة لو كان في الكائن أو المصفوفة كائنات ومصفوفات أخرى داخله، فيمكننا استعمال أنماط معقّدة على يسار جملة الإسناد لنستخرج تلك المعلومات.
في الشيفرة أدناه، نجد داخل الكائن options كائنًا آخر في الخاصية size، ومصفوفة في الخاصية items. النمط على يسار جملة الإسناد لديه ذات البنية تلك لتستخرج هذه القيم من الكائن على يمينه:
// نقسم الإسناد بالتفكيك على أكثر من سطر لتوضيح العملية let { size: { // هنا يكون المقاس width, height }, items: [item1, item2], // وهنا نضع العناصر title = "Menu" // ليست موجودة في الكائن (ستُستعمل القيمة المبدئية) } = options;
alert(title); // Menu alert(width); // 100 alert(height); // 200 alert(item1); // Cake alert(item2); // Donut هكذا تُسند كلّ خاصيات options (عدا extra الناقصة يسار عبارة الإسناد) إلى المتغيرات المقابلة لها:
destructuring-complex.png
وفي النهاية يكون لدينا المتغيّرات width وheight وitem1 وitem2 وtitle من تلك القيمة المبدئية. لاحظ ألّا وجود لمتغيّرات تنسخ size وitems إذ ما نريد هو محتواها لا هي.
مُعاملات الدوال الذكية أحيانًا وأنت تعمل تجد نفسك تكتب دالة لها مُعاملات كثيرة وأغلبها اختيارية. يحدث هذا غالبًا مع دوال واجهات المستخدم. عُدّ أنّ لديك دالة تُنشئ قائمة، وللقائمة عَرض وارتفاع وعنوان وقائمة عناصر وغيرها.
هكذا تصنع تلك الدالة بالأسلوب الخطأ:
function showMenu(title = "Untitled", width = 200, height = 100, items = []) { // ... } تكمن المشكلة (في الحياة الواقعية) في تذكّر ترتيب تلك الوُسطاء. صحيح أنّ بيئات التطوير تفيدنا هنا عادةً -خصوصًا لو كان المشروع موثّق توثيقًا ممتازًا- ولكن مع ذلك فالمشكلة الأخرى هي طريقة استدعاء الدالة لو كانت كلّ مُعاملاتها المبدئية مناسبة لنا.
نستدعيها هكذا؟
// نضع undefined لو كانت القيم المبدئية تقوم بالغرض showMenu("My Menu", undefined, undefined, ["Item1", "Item2"]) جريمة بحقّ الجمال. ورويدًا رويدًا تصير مستحيلة القراءة حين نُضيف مُعاملات أخرى.
التفكيك لنا بالمرصاد… أعني للعون! فيمكننا تمرير المُعاملات بصيغة كائن، وستُفكّكها الدالة حالًا في متغيرات:
// نمرّر كائنًا إلى الدالة let options = { title: "My menu", items: ["Item1", "Item2"] };
// ...ومباشرة تفكّها وتضعها في متغيرات function showMenu({title = "Untitled", width = 200, height = 100, items = []}) {
// title, items – هذه من options // width, height – نستعمل القيم المبدئية alert( `${title} ${width} ${height}` ); // My Menu 200 100 alert( items ); // Item1, Item2 }
showMenu(options); يمكننا أيضًا استعمال التفكيك الأكثر تعقيدًا (مع الكائنات المتداخلة وتغيير الأسماء بالنقطتين الرأسيتين):
let options = { title: "My menu", items: ["Item1", "Item2"] };
function showMenu({ title = "Untitled", width: w = 100, // نضع width في w height: h = 200, // ونضع height في h items: [item1, item2] // أوّل عنصر في items يصير item1، وثاني عنصر يصير item2 }) {
showMenu(options); صياغة الدالة الكاملة تتطابق مع صياغة الإسناد بالتفكيك:
function({ incomingProperty: varName = defaultValue ... }) وحينها متى ما تمرّر كائن على أساس أنّه مُعامل، نضع الخاصية incomingProperty في المتغير varName وقيمته المبدئية هي defaultValue.
لاحظ بأنّ هذا النوع من التفكيك ينتظر مُعاملًا واحدًا على الأقل في الدالة showMenu(). لو أردنا أن تكون كلّ القيم كما هي مبدئيًا، فعلينا تقديم كائن فارغ:
showMenu({}); // هكذا، كل القيم كما هي مبدئيًا
showMenu(); // هذا سيصرخ علينا بخطأ يمكننا إصلاح هذه المشكلة بتحديد {} قيمةً مبدئيةً لكامل الكائن الذي يحوي المُعاملات:
showMenu(); // Menu 100 200 ملخص يتيح الإسناد بالتفكيك ربط الكائن أو المصفوفة مع متغيرات عديدة أخرى، وآنيًا.
صياغة الكائن الكاملة هي:
let {prop : varName = default, ...rest} = object ويعني هذا بأنّ الخاصية prop تصير في المتغيّر varName، وفي حال لم توجد هذه الخاصية فستُستعمل القيمة المبدئية default.
تُنسح حاصيات الكائنات التي لا ترتبط إلى الكائن rest.
صياغة المصفوفة الكاملة هي:
let [item1 = default, item2, ...rest] = array يصير أوّل عنصر في item1 وثاني عنصر في item2 وباقي المصفوفة يصير باقيًا في rest.
يمكن أيضًا استخراج البيانات من المصفوفات/الكائنات المتداخلة، ويلزم أن تتطابق بنية على يسار الإسناد تلك على يمينه.
يعتبر موقع منتديات هندسة بلا حدود من المنتديات المشهورة والمهمة ومن المواقع الهندسية العربية على الانترنت ،وحتى الآن عدد الأعضاء المنتسبين له في المنتديات كأكبر تجمع هندسي عربي حتى الآن.
تصميم متاجر الكترونية
تصميم متاجر
الإسناد بالتفكيك (Destructuring assignment) في جافاسكربت
هام جداً: قوانين المساهمة في المواضيع. انقر هنا للمعاينة
احترم مواضيع الآخرين ليحترم الآخرون مواضيعك لا تحتكر ال موضوع لنفسك بإرسال عدة مساهماتمتتالية عند طرح موضوع يجب أن تتأكد أن عنوان الموضوع مناسب او لا تحل بحسن الخلق و بأدب الحوار و النقاش < لا تنس أن اختلاف الرأي لا يفسد للود قضية, فلاتتهجم على عضو بدعوى أنه لا يشاطرك الرأي < ان قطعت عهدآ مع عضو فأوفي بوعدك لأنه دين عليك إن حصل خلاف بينك و بين عضو حول مسألة ما فلا تناقشا المشكله على العام بل على الخاص ان احترمت هذه الشروط البسيطة, ضمنت حقوقك و عرفت واجباتك. و هذه افضل طريقة تضمن بها لنفسك ثم لمساهماتك و مواضيعك البقاء و لمنتداك الإزدهار في موقعنا إدارة موقع ومنتديات هندسة بلا حدود للاعلانات والسيو
يعتبر موقع منتديات هندسة بلا حدود من المنتديات المشهورة والمهمة ومن المواقع الهندسية العربية على الانترنت ،وحتى الآن عدد الأعضاء المنتسبين له في المنتديات كأكبر تجمع هندسي عربي حتى الآن .ويهدف الموقع إلى نشر المعرفة الهندسية وتقديم كل ماله فائدة للمهندسين والفنيين والمهتمين من خلال أقسامه العلمية والهندسية المتعددة ،بالإضافة إلى وجود أقسام عامة تستقطب الكثير لمختلف النقاشات الهادفة.
لا مانع من الاقتباس واعادة النشر شريطة ذكر المصدر منتديات هندسة بلا حدود. الآراء والتعليقات المنشورة تعبر عن رأي أصحابها فقط - اقرأ قوانين المنتدى.تصميم منتديات هندسة بلا حدود نبيل الدم