استخدام الوضع التفاعلي REPL في Node.js


استخدام الوضع التفاعلي REPL في Node.js September 23, 2022 at 10:03PM

حلقة اقرأ-قيِّم-اطبع أو REPL -اختصارًا للعبارة Read Evaluate Print Loop- هي صدفة تفاعلية interactive shell تعالج تعابير جافاسكربت البرمجية ضمن بيئة نود، حيث تقرأ تلك الصدفة الشيفرات التي يدخلها المستخدم وتُصرّفها ثم تُقيّم نتيجتها وتطبع تلك النتيجة للمستخدم على الشاشة آنيًا، وتكرر ذلك لحين خروج المستخدم من تلك الصدفة، وتأتي REPL مثبتة مسبقًا مع نود، وتسمح لنا باختبار واستكشاف شيفرات جافاسكربت داخل بيئة نود بسرعة ودون الحاجة لحفظها أولًا داخل ملف ثم تنفيذها، وسيلزمك في هذا الفصل للمتابعة معرفة بأساسيات لغة جافاسكريبت، ولبيئة نود مُثبتة على الجهاز.

الدخول والخروج من الوضع REPL

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

node

سيدخلنا ذلك في وضع التفاعلي:

>

حيث يشير الرمز ‎>‎ في بداية السطر لإمكانية إدخالنا شيفرات جافاسكربت لتُعالج، ويمكننا تجربة ذلك بجمع عددين كالتالي:

> 2 + 2

نضغط زر الإدخال ENTER لتُقيّم صدفة نود ذلك التعبير البرمجي وتطبع نتيجته مباشرةً:

4

للخروج من ذلك الوضع يمكننا إما كتابة الأمر ‎.exit أو الضغط من لوحة المفاتيح على الاختصار CTRL+D، أو الضغط مرتين على الاختصار CTRL+C، للخروج والعودة إلى سطر الأوامر.

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

تنفيذ شيفرة جافاسكربت ضمن REPL

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

ندخل أولًا إلى الوضع REPL كما تعلمنا:

node

ونُدخل التعبير البرمجي ونضغط زر الإدخال لتنفيذه:

> 10 / 5

نحصل على الخرج التالي وهو ناتج العملية السابقة:

2

يمكن أيضًا مثلًا تنفيذ العمليات على السلاسل النصية، ولنختبر ذلك بتنفيذ ضم سلسلتين نصيتين كالتالي:

> "Hello " + "World"

وسيظهر لنا نتيجة ضم السلسلتين:

'Hello World'

نلاحظ ظهور النص في النتيجة محاطًا بعلامات اقتباس مفردة بدلًا من علامات الاقتباس المزدوجة، ففي جافاسكربت لا يؤثر نوع علامات الاقتباس على قيمة السلسلة النصية، لذا يستخدم الوضع REPL عند إظهار نتيجة فيها سلسلة نصية علامات الاقتباس المفردة دومًا.

استدعاء التوابع

يستخدم التابع العام console.log أو توابع طباعة الرسائل المشابهة له كثيرًا في بيئة نود، حيث يمكننا داخل REPL استدعاء التوابع أيضًا، فلنجرب مثلًا أمر طباعة رسالة كالتالي:

> console.log("Hi")

سيُستدعى التابع وتظهر نتيجة التنفيذ التالية:

Hi
undefined

يمثل السطر الأول نتيجة استدعاء التابع console.log، والذي يطبع الرسالة إلى المجرى stdout والذي يمثل الشاشة، ولأن الوظيفة طباعة وليس إعادة عبر التعبير return كنتيجة لتنفيذ التابع، نلاحظ عدم وجود علامات الاقتباس حولها، بينما السطر الثاني يعرض القيمة undefined وهي النتيجة التي أعادها التابع بعد انتهاء تنفيذه.

تعريف متغيرات

تُستخدم المتغيرات variables أيضًا بكثرة خلال كتابتنا للشيفرات البرمجية ولا نكتفي بالتعامل مع القيم مباشرة، لذا يتيح لنا REPL إمكانية تعريف المتغيرات تمامًا كما لو كنا نكتبها ضمن ملفات جافاسكريبت، ويمكننا اختبار ذلك كالتالي:

> let age = 30

تظهر لنا النتيجة التالية بعد ضغط زر الإدخال:

undefined

كما لاحظنا سابقًا عند استدعاء التابع console.log كانت القيمة التي يعيدها هي undefined، وهنا أيضًا جرى تعريف المتغير age ولم نُعد أي قيمة، وسيكون ذلك المتغير متاحًا حتى الانتهاء والخروج من جلسة REPL الحالية، ولاختبار ذلك نستخدم المتغير age ضمن عملية ما ولتكن ضربه بعدد كالتالي:

> age * 2

تظهر لنا نتيجة العملية بعد الضغط على زر الإدخال:

60

نلاحظ أن REPL يعيد ويطبع لنا نتيجة التعبير البرمجي فورًا، لذا لا نحتاج لاستخدام التابع console.log في كل مرة نريد طباعة قيمة على الشاشة، حيث سيطبع تلقائيًا أي قيمة يعيدها الأمر المُدخل.

إدخال الشيفرات متعددة الأسطر

يدعم REPL أيضًا إدخال الشيفرات متعددة السطر، ولنختبر ذلك ننشئ تابعًا يضيف القيمة 3 إلى العدد المُمرر له، ونبدأ تعريفه بإدخال أول سطر منه كالتالي:

const add3 = (num) => {

وبعد الضغط على زر الإدخال ستلاحظ تغير الرمز < في أول السطر إلى رمز النُقط الثلاث:

...

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

return num + 3;
}

وبعد إدخال آخر سطر الحاوي على قوس الإغلاق للتابع، ستظهر لنا القيمة undefined، والتي تدل على القيمة المُرجعة من أمر إسناد الدالة إلى الثابت، ونلاحظ عودة الرمز في بداية السطر إلى رمز إدخال الأوامر ‎>‎ بدلًا من النقط ...، وتظهر لنا قيمة الأمر المُدخل:

undefined
>

يمكننا الآن استخدام الدالة التي عرفناها add3()‎ بتمرير قيمة لها كالتالي:

> add3(10)

ويظهر لنا نتيجة الإضافة التي تعيدها الدالة كالتالي:

13

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

التعرف على الاختصارات في REPL

يوفر REPL عدة اختصارات تسهل عملية ادخال الشيفرات وتوفر الوقت، فمثلًا يحفظ REPL -كما معظم الصدفات- سجلًا بالأوامر المدخلة السابقًا لنتمكن من الرجوع إليها بدلًا من إعادة إدخالها يدويًا مرة أخرى.

جرب مثلًا كتابة القيمة النصية الطويلة التالية:

> "The answer to life the universe and everything is 32"

يظهر لنا النص نفسه كنتيجة لذلك الأمر:

'The answer to life the universe and everything is 32'

الآن إذا أردنا إدخال النص السابق نفسه، لكن مع اختلاف وهو تبديل العدد 32 إلى 42، فيمكننا ذلك عبر الضغط على مفتاح السهم العلوي UP من لوحة المفاتيح للوصول إلى آخر قيمة أدخلناها:

> "The answer to life the universe and everything is 32"

بعدها يمكننا تحريك المؤشر داخل النص وإزالة العدد 3 وتبديله إلى العدد 4 ونضغط زر الإدخال ENTER مجددًا:

'The answer to life the universe and everything is 42'

يمكن بالضغط المستمر على السهم العلوي UP الرجوع في سجل تاريخ الأوامر المدخلة سابقًا واحد تلو الآخر، وبالمقابل يمكن الضغط على مفتاح السهم السفلي DOWN للتقدم إلى الأمام في سجل تاريخ الأوامر، ويمكن بعد الانتهاء من تفحص سجلات الأوامر المُخزنة الضغط مرارًا على مفتاح السهم السفلي DOWN إلى حين العودة إلى سطر الإدخال الفارغ لكتابة أمر جديد، ويمكن الوصول إلى قيمة آخر نتيجة عبر محرف الشرطة سفلية _، ولاختبار ذلك نكتب الرمز _ ثم نضغط على زر الإدخال:

> _

سيظهر لنا السلسلة النصية التي أدخلناها مؤخرًا:

'The answer to life the universe and everything is 42'

يتيح REPL أيضًا ميزة الإكمال التلقائي للتوابع والمتغيرات والكلمات المفتاحية أثناء كتابة الشيفرة، فمثلًا إذا أردنا استخدام التابع العام Math.sqrt لحساب الجذر التربيعي لعدد يمكننا فقط كتابة الأحرف الأولى لذلك الاستدعاء كالتالي مثلًا:

> Math.sq

ثم الضغط على زر الجدولة تاب TAB ليكمل لنا REPL كتابة باقي اسم التابع بشكل صحيح كالتالي:

> Math.sqrt

وعندما يكون هناك أكثر من طريقة لإكمال الأمر، سيظهر لنا جميع الاحتمالات الممكنة، فمثلًا إذا حاولنا استدعاء تابع ما من الصنف Math كالتالي:

> Math.

بالضغط على زر الجدولة مرتين سيظهر لنا جميع الاحتمالات الممكنة للإكمال التلقائي لذلك الأمر:

> Math.
Math.__defineGetter__      Math.__defineSetter__      Math.__lookupGetter__
Math.__lookupSetter__      Math.__proto__             Math.constructor
Math.hasOwnProperty        Math.isPrototypeOf         Math.propertyIsEnumerable
Math.toLocaleString        Math.toString              Math.valueOf

Math.E                     Math.LN10                  Math.LN2
Math.LOG10E                Math.LOG2E                 Math.PI
Math.SQRT1_2               Math.SQRT2                 Math.abs
Math.acos                  Math.acosh                 Math.asin
Math.asinh                 Math.atan                  Math.atan2
Math.atanh                 Math.cbrt                  Math.ceil
Math.clz32                 Math.cos                   Math.cosh
Math.exp                   Math.expm1                 Math.floor
Math.fround                Math.hypot                 Math.imul
Math.log                   Math.log10                 Math.log1p
Math.log2                  Math.max                   Math.min
Math.pow                   Math.random                Math.round
Math.sign                  Math.sin                   Math.sinh
Math.sqrt                  Math.tan                   Math.tanh
Math.trunc

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

يمكننا في أي وقت الحصول على سطر فارغ جديد لإدخال الأوامر بالضغط على الاختصار CTRL+C، وذلك دون تنفيذ الأمر الجاري كتابته في السطر الحالي.

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

أوامر REPL

يوفر REPL كلمات مفتاحية خاصة تساعدنا في التحكم به، ويبدأ كل من تلك الأوامر برمز النقطة . سنتعرف عليها.

الأمر ‎.help

لعرض كل الأوامر المتاحة ضمن REPL يمكننا استخدام الأمر ‎.help كالتالي:

> .help

سيظهر لنا جميع الأوامر المتاحة الخاصة بالوضع REPL وهي قليلة لكن مفيدة:

.break    Sometimes you get stuck, this gets you out
.clear    Alias for .break
.editor   Enter editor mode
.exit     Exit the repl
.help     Print this help message
.load     Load JS from a file into the REPL session
.save     Save all evaluated commands in this REPL session to a file

Press ^C to abort current expression, ^D to exit the repl

يفيد تنفيذ هذا الأمر في حال نسيان الأوامر المتاحة أو وظيفة كل منها.

الأمران ‎.break و ‎.clear

تظهر فائدة الأمران ‎.break و ‎.clear خلال كتابتنا الشيفرة متعددة الأسطر إذ تساعد على الخروج من ذلك الوضع، ولنختبر ذلك بكتابة أول سطر من حلقة التكرار for كالتالي:

for (let i = 0; i < 100000000; i++) {

بدلًا من إكمال كتابة أسطر ذلك الأمر يمكننا تنفيذ الأمر ‎.break أو الأمر ‎.clear للخروج:

.break

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

الأمران ‎.save و ‎.load

يُمكّننا الأمر ‎.save من حفظ كافة الشيفرات التي أدخلناها منذ بداية جلسة REPL الحالية إلى ملف جافاسكربت، بالمقابل يُمكّننا الأمر ‎.load من تنفيذ شيفرات جافاسكربت من ملف خارجي داخل REPL، وذلك بدلًا من كتابة تلك الشيفرات يدويًا، و لاختبار ذلك نخرج أولًا من الجلسة الحالية إما بتنفيذ الأمر ‎.exit أو باستخدام الاختصار CTRL+D، ونبدأ جلسة REPL جديدة بتنفيذ الأمر node، حيث ستحفظ كل الشيفرات التي سنقوم بكتابتها منذ الآن داخل الملف عند استخدامنا لأمر الحفظ ‎.save لاحقًا.

نُعرّف مصفوفة من الفواكه:

> fruits = ['banana', 'apple', 'mango']

في سطر النتيجة سيظهر:

[ 'banana', 'apple', 'mango' ]

نحفظ الآن المتغير السابق إلى ملف جديد بالاسم fruits.js كالتالي:

> .save fruits.js

ستظهر رسالة تؤكد حفظ الملف بنجاح:

Session saved to: fruits.js

مكان حفظ ذلك الملف هو نفس مسار المجلد الذي بدأنا منه جلسة REPL من سطر الأوامر، فمثلًا لو كان مسار سطر الأوامر عندها هو مجلد المنزل home للمستخدم، فسيُحفَظ الملف داخل ذلك المجلد.

والآن نخرج من الجلسة الحالية ونبدأ جلسة جديدة بتنفيذ الأمر node مرة أخرى، ونُحمِّل ملف fruits.js الذي حفظناه سابقًا بتنفيذ الأمر ‎.load كالتالي:

> .load fruits.js

ليظهر لنا:

fruits = ['banana', 'apple', 'mango']

[ 'banana', 'apple', 'mango' ]

قرأ الأمر ‎.load كل سطر داخل ذلك الملف ونفذه تمامًا كطريقة عمل مفسر جافاسكربت، حيث أصبح بإمكاننا الآن استخدام المتغير fruits كما لو أننا أدخلناه سابقًا يدويًا ضمن الجلسة الحالية، ولنختبر ذلك ونحاول الوصول لأول عنصر من تلك المصفوفة:

> fruits[1]

نحصل على الخرج المتوقع:

'apple'

ويمكن تحميل أي ملف جافاسكربت باستخدام الأمر ‎.load مهما كان، وليس فقط الملفات التي نحفظها، لنختبر ذلك بكتابة ملف جافاسكربت بسيط نُنشئ ملفًا جديدًا ونفتحه باستخدام محرر النصوص:

nano peanuts.js

ثم ندخل ضمنه الشيفرة التالية ونحفظ التغييرات:

console.log('I love peanuts!');

نبدأ جلسة REPL جديدة من نفس مسار المجلد الحاوي على ملف جافاسكربت peanuts.js الجديد بتنفيذ الأمر node، ونُحمِّل الملف إلى الجلسة الحالية بتنفيذ التالي:

> .load peanuts.js

سيُنفذ الأمر ‎.load التعبير البرمجي console ضمن ذلك الملف ويُظهر الخرج:

console.log('I love peanuts!');

I love peanuts!
undefined
>

تظهر فائدة كلا الأمرين ‎.save و ‎.load عند كتابة الكثير من الشيفرات داخل REPL أو عندما نريد حفظ ما أدخلناه خلال الجلسة الحالية ومشاركته ضمن ملف جافاسكربت.

ختامًا

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

ترجمة -وبتصرف- للمقال How To Use the Node.js REPL لصاحبه Stack Abuse.

اقرأ أيضًا

#oqpahameedq

تعليقات