اذهب إلى المحتوى

شرف الدين حفني

الأعضاء
  • المساهمات

    1690
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    2

كل منشورات العضو شرف الدين حفني

  1. تلك الثﻻث نقاط يسمون بالspread syntax وظيفتهم أنهم يقومون بنشر(spread) عناصر المُكرر(iterator) , فمثلاً عند تنفيذ الكود في مثالك , سيتم أولاً عند تنفيذ ال Array(5).keys() بإنشاء مُكرر (iterator) مكون من الأرقام من صفر إلى أربعة وعﻻمة الspread(...) ستقوم بنشر عناصر الiteratorدون الحاجة أن تمر عليهم عنصر عنصر فيتحول المُكرر(iterator) إلى العناصر (0 1 2 3 4) , ومن ثم يتم ضم تلك العناصر في مصفوفة, وللتوضيح أكثر جرب أن تقوم بتنفيذ الشفرة البرمجية console.log(Array(5).keys()) ستﻻحظة طباعة الأتي في الشاشة Array Iterator {} [[Prototype]]: Array Iterator next: ƒ next() Symbol(Symbol.toStringTag): "Array Iterator" عند طباعة الشفرة التالية نﻻحظ تغير ناتج الطباعة console.log(...Array(5).keys()); هنا يُصبح ناتج الطباعة 0 1 2 3 4
  2. يمكنك تحقيق ذلك عن طريق معرفة عدد خانات كل رقم منهم , ويتم ذلك عن طريق ضرب الأس في لوغاريتم العدد للأساس عشرة, فمثلاً إن أخذنا الأعداد التي وضعتها كمثال سيتم التعامل معها بالشكل التالي 100^100 : 100 * log100 = 200 72^15 : 15 * log72 ~ 28 إذاً الرقم الأول أكبر بكل تأكيد ويمكنك التأكد من ذلك الأمر عن طريق الإثبات الرياضي التالي: إذا كان لوغاريتم س^ص= ص*لوغاريتم س وإذا كان عدد خانات س-1 يساوي لوغاريتم س إذاً يمكننا من الفرضين السابقين إستنتاج أن عدد خانات س^ص -1 يساوي ص*لوغاريتم س
  3. هل من الممكن أن توضح المشكلة أكثر؟ مثلاً أ، تقوم برفق صور تعبر عن المشكلة بالإضافة لإرفاق الشفرة البرمجية التي فيها المشكلة حتى نتمكن من المساعدة
  4. مرحباً, الخاصية transform-style:preserve-3d تجعل العنصر قابل أن يتعامل العناصر بداخله(children elements) معه بشكل ثﻻثي الأبعاد بدلاً من فقط التعامل مع سطحه, أُنظر إلى المثال التالي <!DOCTYPE html> <html> <head> <style> #div1 { position: relative; height: 200px; width: 200px; margin: 100px; padding: 10px; border: 1px solid black; } #div2 { padding: 50px; position: absolute; border: 1px solid black; background-color: red; transform: rotateY(60deg); } #div3 { padding: 40px; position: absolute; border: 1px solid black; background-color: yellow; transform: rotateY(-60deg); } </style> </head> <body> <div id="div1"> <div id="div2"> HELLO <div id="div3">world</div> </div> </div> </body> </html> ذلك المثال إن قمت بتشغيله عندك ستجد مربعين فوق بعضهم البعض, المربع الأب وهو div2 والمربع الثاني بداخله div3 أي أن المربع الأصغر div3 يتعامل مع المربع الكبير div2 على أنه سطح ثنائي الأبعاد, بينما بعد إضافة الخاصية للمربع الأب div2 ستجد العنصر الأصغر div3 بدلاً من أن يكون موضوع فوقه تعاملاً مع سطحه ثنائي الأبعاد, ستجده يعبر منه حيث قام بإعتباره جسم ثﻻثي الأبعاد وليس مجرد سطح بالنسبة للمثال الذي قمت أنت بوضعه فإن قمت بإزالة الخاصية ستجد أن المربع الثاني المسمى back لن يظهر , سيظهر فقط المربع front
  5. المشكلة إن suneditor-react يحتوي على بعض المشاكل عند العمل مع next js ولكن يمكن حل مشكلتك عن طريق عمل إستدعاءimport لملف الجافاسكريبتjavascript المسؤل عن الbuttonList يدوياً , فبدلاً من كتابة import {buttonList} from "suneditor-react" يمكنك تحويلها إلى الشكل التالي import { basic, formatting, complex } from "suneditor-react/dist/misc/buttonList"; وتستطيع تضمين الأزرار في الsuneditor عن طريق الشفرة البرمجية التالية <SunEditor setOptions={{ buttonList: basic.concat(formatting).concat(complex) }} />
  6. الhash table (جدول التشفير) يعمل بالشكل التالي يتم عمل عملية hashing للمفتاح يتم تخزين قيمة المفتاح في الذاكرة في العنوان الذي حصلنا عليه من عملية الhashing عندما نريد الحصول على القيمة المُخزنة في قاعدة البيانات نقوم بكُل بساطة بعملية hashing للمفتاح الذي نريد الحصول على قيمته ومن ثم نذهب للذاكرة في العنوان الذي حصلنا عليه من عملية الhashing ونأتي بالقيمة عملية بسيطة والتعقيد الوقتي لها (Time complexity) أقل نوع وهو الثابت O(1) بالنسبة للأشجار(trees) فيتم فيها تخزين العناصر بشكل مرتب وعندما نريد الحصول على عنصر معين نقوم بالنظر في منتصف العناصر, إن كان العنصر المحصول عليه أكبر من المُراد نبحث في الجزأ الأيسر من العناصر( على فرض أن العناصر في الشجرة مرتبة من اليسار لليمين بشكلٍ تصاعدي) , إن كان العنصر أصغر نبحث في الجزأ الأيمن. تلك العملية في المتوسط تأخذ وقت O(logn) حسنا لماذا إذا نقوم بإستخدام الأشجار بدلاً من الجداول؟ ببساطة لأن بسبب أن الجداول تتعامل بعنوان الذاكرة وليس ترتيب معين للعناصر يوجد بعض العمليات التي تكون غير عملية بإستخدام الجداول, مثلاً ﻻ نستطيع أن نعثر على جميع العناصر الأقل من قيمة معينة أو أكبر من قيمة معينة, ﻻ نستطيع العثور عﻻ جميع العناصر بين قيمتين select * where id >5000 select * where id between(1000, 2000) select all where id <1000 كل تلك العمليات تكون غير عملية بالمرة بالنسبة للجدول , بالإضافة لعمليات الترتيب التي تكون مجهدة بالنسبة للأشجار لأنها تتعامل مع العناصر مرتبة وتخزن العناصر على هيئة قائمة وليس على اساس عنوان في الذاكرة فيكون تلك العمليات سهلة , فنضحي بشئٍ من السرعة مقابل الكثير من المرونة .
  7. المشكلة أنك لم تحدد للدالة getline المصدر الذي ستتلقى منه البيانات حيث أن تلك الدالة ليست مصممة فقط لقراءة البيانات من شاشة الإدخال القياسية (standard input) بل أنها تستقبل المدخلات من أي مصدر تحدده مثلاً من ملف نصي لجعل الشفرة البرمجية خاصتك تعمل يجب إعطاء مصدر البيانات كparameter للدالة string s; std::getline(cin,s);
  8. جرب أن تقوم بتثبيت ال file loader npm i file-loader إن لم يعمل معك قم بضغط مجلدات المشروع وإرسالها لتحديد الخطأ بدقة أكبر
  9. سبب هذا الخطأ هو أن مجموعة أدوات تطوير ريدكس(redux dev-tools) تعمل على المتصفح بينما الnext js تعمل على الخادم مما يسبب مشاكل, فعندما نقوم بإستخدام React. js كنا نقوم بكتابة شفرة برمجية كتلك const store = createStore(reducer , window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()) ولكن عند كتابة تلك الشفرة في Next.js سيتسبب ذلك بمشكلة لأن كما أخبرتك أن الnext js تعمل على الخادم أولاً حتى تحقق ال static-site-generating أو ال server-side rendering و الكائن window هو أحد الكائنات الخاصة بالمتصفح وبما أن الشفرة البرمجية تعمل عند الخادم أولاً فبالتالي لن يمكنها الوصول إلى الكائنات الخاصة بالمتصفح. الحل: أن نقوم بالتأكد أولاً من كون الشفرة البرمجية يتم تنفيذها على المتصفح وليس على الخادم حتى ﻻ تتسبب بأخطاء, ويمكننا التحقق من ذلك عن طريق التحقق من توفر الكائن window , ويمكن كتابة الشفرة البرمجية على النحو التالي: const enhancer = (typeof window !== 'undefined' && window.devToolsExtension) ? window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() : f => f const store = createStore(reducer ,enhancer); هكذا نقوم بالتأكد أولاً أن الشفرة البرمجية تعمل بالمتصفح وأن مجموعة الأدوات تعمل بنجاح
  10. ليس تماماً , فإن الجافاسكريبت على عكس اللغات التي تعمل في المستوي المنخفض (low level languages) التي مكنك بإستخدامها إختيار ماإن كنت تريد إرسال البيانات بالمرجعية أم بالقيمة, فإن الأمر في الجافا سكريبت مختلف قليلاً, حيث يتم تلقائياً إرسال البيانات البدائية (primitive data types) بالقيمة , وأما الكائنات فيتم إرسال نسخة من المرجعية(copy of reference). حيث ﻻ يمكنك تغيير الكائن الذي يتم تمريره إلى الدالة ولكن يمكنك تغيير قيمته, لنأخذ مثالاً لتوضيح الأمر: function test(obj){ obj={}; } هذا السطر لن يؤثر على الكائن obj خارج الدالة حيث أنك تحاول تغيير مرجعية الكائن نفسه والذي هو غير مقبول في الجافا سكريبت function test(obj){ obj.a="hello khaled"; } بينما هذا السطر سيقوم بتغيير قيمة الخاصية a لدي الكائن obj حيث أنك تحاول فقط تغيير خواص الكائن والذي يُعد مقبولاً في الجافاسكريبت فلو قمنا بكتابة شفرة برمجية لتجربة الدوال بالأعلى سنجد قيمة الطباعة كما في الشكل بالأدنى function test(obj){ obj={}; } let a={ name:"sharaf" } test(a) console.log(a)/////////سنﻻحظ أن قيمة الكائن لن تتغير على الإطﻻق //////////////////////////////////// function test(obj){ obj.a="test" } let a={ name:"sharaf } test(a) console.log(a)///////////سنﻻحظ هنا تغيير في قيم الكائن
  11. قم بفتح الterminalخاصتك وقم بالذهاب إلى مسار البرنامج cd /opt/lampp/ ومن ثم قم بتشغيل برنامج xampp عبر الterminal sudo ./xampp سيظهر لك قائمة من الأوامر الممكن إستخدامها , أهمها بالنسبة لنا الأمرين start وهو لتشغيل خدمات قاعدة البيانات وخادم أباتشي sudo ./xampp start والأمرstop وهو لإيقاف نفس الخدمات السابقة التي قمنا بتشغيلها sudo ./xampp stop
  12. لإيجاد أول خانة في الرقم نحتاج إلى القيام بالخطوات التالية أولاً العثور على عدد الخانات وذلك يمكن فعله عن طريق إيجاد لوغاريتم الرقم للأساس 10 من المعادلة السابقة سنحصل على عدد الخانات -1 الأن نقوم برفع العشرة لأس الناتج الذي عثرنا عليه فمثلاً العدد 989 عدد خاناته 3 , المعادلة السابقة ناتجها 2 , نقوم إذا برفع 10 للأس 2 والذي يعطينا 100 نقوم بقسمة العدد على ناتج رفع العشرة للأس, أي نقوم بقسمة ال989 في مثالنا على 100 ونقم بتقريب الناتج , سنعثر على أول خانة في الرقم ويمكن تمثيل ذلك برمجياً عن طريق الشفرة التالية بلغة الجافا int number = scan.nextInt(); int firstDigit; int totalDigits = (int) Math.log10(number); firstDigit = (int) (number/ (int) Math.pow(10,totalDigits));
  13. أجل يمكنك تغيير الإتجاه عن طريق الخاصية flexDirection, إن قمت بجعل الخاصية flexDirection إلى row تجد وقتها العناصر مصطفة بالطول, إن قمت بتغييرها إلى colتجد العناصر داخل الview مصطفة بالعرض كما في الشكل التالي <View style={{ flexDirection:row, hight: 50, width:20, backgroundColor:"red" }} /> هذا من أجل إصطفاف العناصر بعضهم بجانب بعض بالطول <View style={{ flexDirection:col, hight: 50, width:20, backgroundColor:"red" }} /> وذلك بهدف إصطفافهم بعضهم فوق بعضٍ بالعرض
  14. هذا لأن القائمة لم تأخذ إرتفاع الصفحة بالكامل, إنما فقط أخذت الإرتفاع الكافي لنشر عناصرها, لجعلها تأخذ الإرتفاع بالكامل قم بتعديل الstyleالخاص بالقائمة والعناصر التي تقوم بإحتواء القائمة عبر إضافة class الخاص بالإرتفاع h-100 <div class="container h-100"> <div class="row h-100"> <!-- Start right menu --> <div class="col-md-2 col-xs-2 h-100"> <div class="menu-outer h-100"> <div class="menu-icon"> <div class="bar"></div> <div class="bar"></div> <div class="bar"></div> </div> <nav> <ul> <li><a href="#">الرئيسية</a></li> <li><a href="#">المدونة</a></li> <li><a href="#">من نحن</a></li> <li><a href="#">إتصل بنا</a></li> </ul> </nav> وقتها ستجد القائمة أخذت إرتفاع الصفحة بأكملها
  15. الخطأ في أنك تقوم بإرجاع ناتج الدالة بشكل خاطئ حيث تقوم بإرجاعه على هذ الشكل [ [ { params: {} }, { params: {} } ], [ { params: {} } ] ] بينما الصحيح أن تقوم بإرجاعه على هذا النحو [ { params: {} }, { params: {} }, { params: {} } ] مما يعني أن بدلاً من كتابة return { paths: [ blogPosts, authorPaths, ], fallback: false, } } قم بكتابة return { paths: [ params:{ blogPosts, authorPaths } ], fallback: false, } }
  16. سبب تلك الحلقة الﻻ نهائية أنك تقوم بإستخدام useEffect وتجعلها معتمدة على المتغير meetings وفي نفس الوقت تقوم بتغيير نفس المتغير في نفس دالة الuseEffect مما يعيد نداؤها مرة أخرى ويجعلها بالتالي تغير المتغير مرة أخرى إلى مالا نهاية, الحل أن تقوم بعمل دالتان للuseEffect الأولى تجعلها ﻻ تعتمد على متغيرات من الأساس, وتلك التي تقوم فيها بتغيير الmeetings الثانية المعتمدة على متغير الmeetings تقوم فيها بعمل باقي الشفرة البرمجية التي ﻻ تغير من هذا لمتغير
  17. ﻻ يجب تعلمها مادمت ﻻ تحتاجها , وضع الxml كجزأ من الإختصار لأنه في بدايات التقنية كان يتم إستخدام الxml كنوع الformat لإرسال وإستقبال البيانات, ولكن في الوقت الحالي غالباً يتم إستخدام الjson بدلاً من الxml
  18. ajax: هي إختصار لAsynchronous JavaScript and XML وهي تقنية لإرسال طلبات الHTTP من خﻻل الجافاسكريبت إلى الخادم بشكل متزامن مع باقي الشفرة البرمجية, بمعنى أن الطلب يتم إرساله وإنتظار الرد حتى يصل , وفي الوقت بين ما يتم إرسال الطلب وإستﻻم الرد المتعلق به يتم تنفيذ الشفرات البرمجية للجافاسكريبت بشكل طبيعي دون أن تتوقف الajax يتم إستعمالها عادةً من أجل التعامل مع الخادم دون الحاجة إلى إعادة تحميل الصفحة (reload) وليكون موقع الويب متفاعل مع المستخدم بشكل أكبر فتظهر البيانات بشكل ديناميكي دون الحاجة إلى إعادة تحميل الصفحة كل مرة من أجل إظهار البيانات Websocket:هي تقنية مبنية على الHTTP2 , كما ذكرنا في السابق أن الajax تقوم بإرسال الطلب وإنتظار الخادم حتى يرسل الرد , وهنا ينتهي الطلب وﻻ يستطيع الخادم إرسال بيانات جديدة للعميل إﻻ بعد فتح طلب جديد, بينما في الwebsocket يقوم العميل بفتح الإتصال بينه وبين الخادم , ومن هنا يستطيع كلا من العميل والخادم إرسال بيانات إلى بعضهم البعض دون الحاجة لإرسال طلب جديد كل مرة يتم إستخدام تلك التقنية عادةً في التطبيقات التي تحتاج إلى سرعة عالية في توفر البيانات الحديثة دون تأخير أو كما يقال (real time) مثل تطبيقات الدردشة والألعاب هل يمكن للwebsocket أن تقوم بإستبدال الajax?? الإجابة ﻻ, فكما أوضحت بالأعلى فإن لكل منهما عمله, فﻻ يجب على الwebsocket أن تتعامل مع الAPI أو أن تتعامل مع البيانات التي تتعامل مع بيانات لن يحدث ضرر إن تأخرت بضع أجزاء من الثانية
  19. الJWT(JSON web Token) ليست أفضل من الsessions في المطلق, وإنما تقوم بحل بعض المشكلات التي تنتج من إستخدامنا للsessions أو بالأدق المشاكل التي تنتج من إعتمادنا على المصادفة من خﻻل الخادم (server-side authentication) من تلك المشاكل: تخزين الsessions, حيث يكون لنا خيارين , إما تخزينها في قواعد البيانات والذي يؤدي إلى زيادة التكلفة وضعف في الأداء نسبياً الخيار الثاني هو تخزينها في الذاكرة , وذلك ليس حل فعال إن كان التطبيق يتم خدمته من خﻻل أكثر من خادم على أكثر من حاسوب , لأن الذاكرة ليست مشتركة مما قد يسبب مشاكل وأخطاء في عملية المصادقة أما بالنسبة للjwt فيكون الtoken مُخزن على حاسوب العميل فﻻ يحتاج الخادم إلى تخزينه وﻻ تقابلنا المشاكل السابقة , إذا للjwt المميزات الأتية أقل في التكلفة حيث لا يحتاج إلى قاعدة بيانات في الأغلب للتخزين ﻻمركزي, بمعنى أن الرموز(tokens) ليست موجودة في مكان واحد (الخادم) وإنما كل عميل يحمل الرمز الخاص به ولكن على الجانب الأخر نجد تحديات عند إستخدام الرموز(tokens) تأمين عملية تخزين الرموز, بما أنها مُخزنة على حاسوب العميل فهذا يجعلها أقل أماناً ويصنع تحدي في عملية الحفاظ عليها تأمين عملية نقلها عبر الشبكة, حيث أنها تُرسل من قِبل العميل فيُمثل أمر إنتقالها بدون أن يتم التجسس عليها تحدياً بالنسبة للمطورين عملية تحديد الرموز كغير صالحةinvalid يُعد من الأمور الشاقة نسبياً بالنسبة للمصادقة عبر الجلسات sessions authentication
  20. ECMAScript هي المعايير(Standards) التي تتبعها لغات الإسكريبت مثل javascript, coffescript, actionscript, livescript وهي تُعد النواة التي بُنيت عليها الجافاسكريبت ,حيث يمكنك إعتبار أن لغات البرمجة مثل جافاسكريبت مثل السيارة , والECMAScript هي المحرك لتلك السيارة(أو النواة أو المعايير كما إتفقنا بالأعلى) حيث النحويات(syntax) في لغة الجافاسكريبت مثل المصفوفات والكائنات والبرمجة كائنية التوجه وكل تلك الأشياء الأساسية يتم إستمدادها من معايير الECMAScript , وكما ذكرنا بما أنها معايير فليست دائما مُتبعة من المتصفحات, فستجد بعض المتصفحات الحديثة تدعم المعايير الجديدة وبعض المتصفحات القديمة لا تدعمها بالنسبة للإختصار فهي مكونة من كلمتين ECMA وهي راجعة إلى منظمة ECMA وهي منظمة تقوم بوضع المعايير وكلمة Script والتي تعبر عن أن تلك المعايير للغات الscripting مثل الجافاسكريبت بالنسبة للإصدارات ستجدها موضحة بالجدول بالأدنى { 1 June 1997 2 June 1998 3 December 1999 4 Abandoned 5 December 2009 5.1 June 2011 6 June 2015[11] ECMAScript 2015 (ES2015) 7 June 2016[12] ECMAScript 2016 (ES2016) 8 June 2017[13] ECMAScript 2017 (ES2017) 9 June 2018[14] ECMAScript 2018 (ES2018) 10 June 2019[15] ECMAScript 2019 (ES2019) 11 June 2020[16] ECMAScript 2020 (ES2020) 12 June 2021[9] ECMAScript 2021 (ES2021) } بالنسبة لES next يُقصد به الإصدار القادم من الECMAScript و ECMA international هي تلك منظمة المعايير التي تكلمنا عنها بالأعلى
  21. من بعد إصدار React 17 أصبحت الdependencies التي ﻻ تقوم بعمل import ل React 17 تقوم بعمل خطأ عند التثبيت , لحل تلك المشكلة يرجى تثبيتها عن طريق الأمر التالي npm install react-facebook-login --legacy-peer-deps هذا الأمر سيجعل الnpm يتغاضي عن تثبيت الإعتماديات الخاصة ب react-facebook-login
  22. يمكنك إنشاء متغير لكل عنصر في المعادلة , وحساب الأُسُس عن طريق الدالة pow المستدعاة من المكتبةcmath ويمكن التعبير عن ماسبق عن طريق الشفرة البرمجية التالية #include <iostream> #include <cmath> using namespace std; int findValueOfZ(int x, int y, int n, int m){ return pow(x,2)+pow(y,3)*n*m //Z=x2+y3nm } int main(){ int x, y, n, m; cin>>x>>y>>n>>m cout<<findValueOfZ(x,y,n,m); }
  23. سبب الخطأ أن الدالة abs تقوم بأخذ قيمة عددية وترجع القيمة المطلقة لها, والتي بدورها أيضا قيمة عددية كما أن المتغير في المصفوفة arr[3] يُعد أيضاً قيمة عددية, وال" " عبارة عن سلسلة نصية, ﻻ يمكنك جمع سلسلة نصية وقيمة عددية في الوقت ذاته, الحل أن تقوم بتحويل القيم العددية إلى سلسلة نصية عن طريق الدالة to_string كما عملت في عﻻمة الجمع رقم إثنين فتصبح الشفرة البرمجية خاصتك على الصيغة التالية string findTrees(int arr[],int n){ string position; int a; if(arr[0]==arr[2]){ a=abs(arr[3]-arr[1]); position=to_string(abs(arr[0]-a))+" " +to_string(arr[1])+' '+to_string(abs(arr[0]-a))+' '+ to_string(arr[3]); }
  24. يوجد بالفعل في c++ مكتبة STL والتي ترمز ل (Standard Template Library) والتي تتكون من أربع مكونات الحاويات: وتعبر عن هياكل البيانات المختلفة مثل vector, set, list, graph, tree المكررات(iterators) :يُستخدمو بالتوازي مع الحاويات من أجل إجراء عمليات على عناصر الحاويات الخوارزميات: هنا يوجد خوارزميات مختلفة لمهام مختلفة , وهنا تجد ما تريده , حيث تجد هنا خوارزميات للبحث والترتيب int x=1, y=0; std::swap(x,y); هذا مثلاً كود من المكتبة من أجل عملية الswapping int *result =std::find(arr.begin(), arr.end(), item) cout<<result-arr.begin() هذا كود من أجل البحث عن عنصر معين في المصفوفة
  25. الوحدة(module) هي كمية من الشفرة البرمجية تخدم غرضاً ما محدداً ويمكن إعادة إستخدامها, وعادةً يتم إستخدام الوحدات لتقسيم البرنامج إلى أجزاء صغيرة من الوحدات بالإضافة لإنشاء أجزاء من الشفرة البرمجية القابلة لإعادة الإستخدام بالنسبة للأمثلة التي وضعتها: فبدلاً من وضع البرنامج كله في ملف واحد كبير مما يصعب من وجود الأخطاء وفهم الشفرة البرمجية بشكل أصعب كما في الشكل التالي const secret = 'SUPER SECRET' // share const john = 'john' const peter = 'peter' const sayHi = (name) => { console.log(`Hello there ${name}`) } sayHi('susan') sayHi('john') sayHi('peter') قمنا بتقسيم البرنامج إلي ثﻻث ملفات, ملف names الذي يحمل البيانات التي نحتاجها في البرنامج حتى يعمل بشكل صحيح(الأسماء) , وملف utils الذي يحتوي على الدوال التي تمثل الوظائف للبرنامج , وملف appالذي يقوم بعمل إستيراد للملفين السابقين ويستدعي وظائفهم حتى يعمل البرنامج.
×
×
  • أضف...