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

1. متغيرات تخزين القيم والمراجع
من المهم للغاية فهم كيفية تحديد القيم المتغيرة في جافا سكريبت لأولئك الذين يرغبون في كتابة تعليمات برمجية صحيحة. يؤدي سوء فهم هذه الآلية إلى كتابة البرامج التي يمكن أن تتغير فيها قيم المتغيرات عن غير قصد.
جافا سكريبت ، إذا كان لدى أحد الكيانات أحد الأنواع البدائية (على وجه الخصوص ، أنواع
Boolean
،
null
،
undefined
،
String
) ، يعمل دائمًا مع قيمة هذا الكيان. بمعنى ، القيمة مكتوبة إلى المتغير المطابق. إذا كنا نتحدث عن كائن (على سبيل المثال ،
Object
،
Array
، أنواع
Function
) ، فعند تعيينه لمتغير ، تتم كتابة مرجع إليه ، العنوان الذي يوجد به في الذاكرة.
النظر في مثال. في مقتطف الشفرة التالي ، تتم كتابة السلسلة إلى
var1
. بعد ذلك ،
var2
كتابة قيمة
var2
إلى متغير
var2
. نظرًا لأن متغير
var1
يحتوي على نوع بدائي (
String
) ، سيتم كتابة نسخة من السلسلة المتوفرة في
var1
إلى
var1
. يسمح لنا ذلك بالنظر إلى
var2
كمتغير مستقل تمامًا عن
var1
، على الرغم من أنه يخزن نفس قيمة
var1
. كتابة قيمة جديدة إلى
var1
لا تؤثر على
var1
.
let var1 = 'My string'; let var2 = var1; var2 = 'My new string'; console.log(var1);
الآن النظر في مثال للعمل مع الكائنات.
let var1 = { name: 'Jim' } let var2 = var1; var2.name = 'John'; console.log(var1);
كما ترون ، نحن هنا نعمل مع متغير
var2
، وما يحدث له ينعكس في متغير
var1
لأنه يخزن مرجعًا لنفس الكائن. من السهل أن نتخيل ما يمكن أن يؤدي إليه هذا في الكود الحقيقي إذا قرر شخص ما أن المتغيرات التي تخزن الكائنات تتصرف مثل المتغيرات التي تخزن قيم الأنواع البدائية. هذا غير سارة بشكل خاص ، على سبيل المثال ، في الحالات التي يقومون فيها بإنشاء دالة تم تصميمها للعمل مع قيمة الكائن التي تم تمريرها إليها ، وهذه الوظيفة غيرت هذه القيمة عن غير قصد.
2. دوائر قصيرة
الإغلاق هو نمط تصميم مهم في JavaScript يتيح لك تنظيم العمل المحمي مع المتغيرات. في المثال التالي ، تقوم
createGreeter()
بإرجاع دالة مجهولة لها حق الوصول إلى الوسيطة الأصلية المتوفرة مع وسيطة
greeting
التي تحتوي على السلسلة
Hello
. تتم كتابة مرجع إلى هذه الوظيفة المجهولة إلى متغير
sayHello
. بعد ذلك ، بغض النظر عن عدد المرات التي نسميها وظيفة
sayHello()
، سيكون
sayHello()
دائمًا الوصول إلى قيمة
greeting
. في هذه الحالة ، لن يكون الوصول إلى
greeting
سوى وظيفة مجهولة المصدر ، يتم تسجيل رابط إليها في
sayHello
.
function createGreeter(greeting) { return function(name) { console.log(greeting + ', ' + name); } } const sayHello = createGreeter('Hello'); sayHello('Joe');
كان هذا مثالا بسيطا جدا. إذا نظرنا إلى شيء أقرب إلى العالم الحقيقي ، يمكننا أن نتخيل ، على سبيل المثال ، وظيفة للاتصال بواجهة برمجة تطبيقات معينة (دعنا نسميها
apiConnect()
) ، والتي عندما يتم استدعاؤها لأول مرة ، يتم تمرير مفتاح وصول API. تقوم هذه الوظيفة بدورها بإرجاع كائن يحتوي على عدة طرق تستخدم مفتاح الوصول إلى واجهة برمجة التطبيقات الذي تم تمريره إلى
apiConnect()
. في هذه الحالة ، يتم تخزين المفتاح في الإغلاق وعند استدعاء هذه الطرق ، لم يعد من الضروري ذكره.
function apiConnect(apiKey) { function get(route) { return fetch(`${route}?key=${apiKey}`); } function post(route, params) { return fetch(route, { method: 'POST', body: JSON.stringify(params), headers: { 'Authorization': `Bearer ${apiKey}` } }) } return { get, post } } const api = apiConnect('my-secret-key');
3. الاحالة المدمرة
إذا لم تستخدم المهمة المدمرة في جافا سكريبت ، فقد حان الوقت لإصلاحها. المهمة المدمرة هي طريقة شائعة لاسترداد خصائص الكائن باستخدام بنية لغوية أنيقة.
const obj = { name: 'Joe', food: 'cake' } const { name, food } = obj; console.log(name, food);
إذا كنت بحاجة إلى تعيين أسماء الخصائص المستخرجة التي تختلف عن تلك الموجودة في الكائن ، فيمكنك القيام بذلك:
const obj = { name: 'Joe', food: 'cake' } const { name: myName, food: myFood } = obj; console.log(myName, myFood);
في المثال التالي ، يتم استخدام التدمير لتمرير القيم المخزنة في خصائص كائن
person
بدقة إلى الدالة
introduce()
. هذا مثال على كيفية استخدام هذا البناء عند الإعلان عن وظيفة لاسترداد البيانات من كائن مع المعلمات التي تم تمريرها إليه. بالمناسبة ، إذا كنت معتادًا على React ، فمن المحتمل أنك رأيت هذا بالفعل.
const person = { name: 'Eddie', age: 24 } function introduce({ name, age }) { console.log(`I'm ${name} and I'm ${age} years old!`); } console.log(introduce(person));
4. عامل الانتشار
عامل الانتشار هو بنية بسيطة إلى حد ما قد تبدو غير مفهومة لشخص غير مستعد. يحتوي المثال التالي على صفيف رقمي ، القيمة القصوى المخزنة التي نحتاج إلى العثور عليها. نريد استخدام الأسلوب
Math.max()
لهذا ، لكن لا يعرف كيفية التعامل مع المصفوفات. هو ، كحجج ، يفترض القيم العددية المستقلة. من أجل استخراج عناصرها من الصفيف ، نستخدم عامل الانتشار ، الذي يشبه ثلاث نقاط.
const arr = [4, 6, -1, 3, 10, 4]; const max = Math.max(...arr); console.log(max);
5. بيان الراحة
يتيح لك مشغل الاستراحة تحويل أي عدد من الوسائط التي يتم تمريرها إلى دالة إلى صفيف.
function myFunc(...args) { console.log(args[0] + args[1]); } myFunc(1, 2, 3, 4);
6. أساليب الصفيف
غالبًا ما توفر أساليب الصفيف للمطور أدوات ملائمة لحل مجموعة متنوعة من مهام تحويل البيانات بشكل جميل. أجيب أحيانًا على أسئلة حول StackOverflow. من بينها ، غالبًا ما توجد تلك المخصصة لشيء مثل تلك أو طرق أخرى للعمل مع صفائف الكائنات. في مثل هذه الحالات تكون أساليب الصفيف مفيدة بشكل خاص.
سننظر هنا في عدة طرق من هذا القبيل ، توحدها مبدأ التشابه بينها. تجدر الإشارة إلى أنني هنا لن أخبركم عن جميع أساليب المصفوفات. يمكنك العثور على قائمة كاملة على
MDN (بالمناسبة ، هذا هو مرجع JavaScript المفضل).
apMap () ، وتصفية () ، والحد من () الأساليب
تتيح لك أساليب الصفيف
map()
،
filter()
و
reduce()
تحويل الصفائف أو تصغير الصفيفات إلى قيمة واحدة (والتي يمكن أن تكون كائنًا).
تقوم الطريقة
map()
بإرجاع صفيف جديد يحتوي على القيم المحولة للصفيف المعالج. يتم تحديد كيفية تحويلها بالضبط في الوظيفة التي تم تمريرها إلى هذه الطريقة.
const arr = [1, 2, 3, 4, 5, 6]; const mapped = arr.map(el => el + 20); console.log(mapped);
تُرجع الطريقة
filter()
صفيفًا من العناصر ، والتحقق من القيم التي ترجع بها الدالة التي تم تمريرها إلى هذه الطريقة.
const arr = [1, 2, 3, 4, 5, 6]; const filtered = arr.filter(el => el === 2 || el === 4); console.log(filtered);
إرجاع الأسلوب
reduce()
قيمة معينة ، وهي نتيجة معالجة جميع عناصر الصفيف.
const arr = [1, 2, 3, 4, 5, 6]; const reduced = arr.reduce((total, current) => total + current); console.log(reduced);
find طرق find () و findIndex () و indexOf ()
indexOf()
السهل الخلط بين أساليب الصفيف
find()
و
findIndex()
و
indexOf()
مع بعضها البعض. فيما يلي تفسيرات لمساعدتك في فهم ميزاتها.
تقوم
find()
بإرجاع العنصر الأول للصفيف الذي يطابق المعايير المحددة. لا تستمر هذه الطريقة في العثور على العنصر المناسب الأول في البحث في الصفيف.
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; const found = arr.find(el => el > 5); console.log(found);
يرجى ملاحظة أنه في مثالنا ، تتوافق المعايير المحددة مع جميع عناصر المصفوفة التي تتبع المعيار الذي يحتوي على الرقم 5 ، ولكن يتم إرجاع العنصر المناسب الأول فقط. هذه الطريقة مفيدة للغاية في المواقف التي يتم فيها استخدام الحلقات لتعداد المصفوفات وتحليلها ، حيث يتم مقاطعة هذه الحلقات عندما يتم العثور على العنصر المطلوب في المصفوفة ، باستخدام عبارة
break
.
findIndex()
طريقة
findIndex()
جدًّا
find()
، لكن بدلاً من إرجاع أول عنصر مناسب في الصفيف ، فإنها تُرجع فهرس ذلك العنصر. لفهم هذه الطريقة بشكل أفضل ، ألق نظرة على المثال التالي ، والذي يستخدم مجموعة من قيم السلسلة.
const arr = ['Nick', 'Frank', 'Joe', 'Frank']; const foundIndex = arr.findIndex(el => el === 'Frank'); console.log(foundIndex);
طريقة
indexOf()
تشبه إلى حد كبير طريقة
findIndex()
، ولكنها تأخذ كوسيطة وليس وظيفة ، ولكنها قيمة عادية. يمكن استخدامه إذا لم تكن هناك حاجة للمنطق المعقد عند البحث عن عنصر الصفيف المطلوب.
const arr = ['Nick', 'Frank', 'Joe', 'Frank']; const foundIndex = arr.indexOf('Frank'); console.log(foundIndex);
▍ Push () و pop () و shift () و unshift ()
تُستخدم
unshift()
push()
و
pop()
و
shift()
و
unshift()
لإضافة عناصر جديدة للصفائف واستخراج العناصر الموجودة بالفعل في الصفائف منها. في هذه الحالة ، يتم تنفيذ العمل مع العناصر الموجودة في بداية أو في نهاية الصفيف.
تتيح لك طريقة
push()
إضافة عناصر إلى نهاية صفيف. يقوم بتعديل الصفيف ، وعند الانتهاء ، يُرجع العنصر المضاف إلى الصفيف.
let arr = [1, 2, 3, 4]; const pushed = arr.push(5); console.log(arr);
يزيل الأسلوب
pop()
العنصر الأخير من الصفيف. يقوم بتعديل الصفيف وإرجاع العنصر الذي تمت إزالته منه.
let arr = [1, 2, 3, 4]; const popped = arr.pop(); console.log(arr);
الأسلوب
shift()
يزيل العنصر الأول من الصفيف ويعيده. كما يعدل الصفيف الذي يطلق عليه.
let arr = [1, 2, 3, 4]; const shifted = arr.shift(); console.log(arr);
يضيف الأسلوب
unshift()
عنصرًا واحدًا أو أكثر إلى بداية صفيف. هو ، مرة أخرى ، يعدل مجموعة. في الوقت نفسه ، بخلاف الطرق الثلاث الأخرى التي تمت مناقشتها هنا ، فإنها تُرجع الطول الجديد للصفيف.
let arr = [1, 2, 3, 4]; const unshifted = arr.unshift(5, 6, 7); console.log(arr);
طرق ▍Slice () و splice ()
تستخدم هذه الطرق لتعديل الصفيف أو لإرجاع جزء من الصفيف.
تقوم طريقة
splice()
بتغيير محتويات الصفيف عن طريق حذف العناصر الموجودة أو استبدالها بعناصر أخرى. إنه قادر على إضافة عناصر جديدة إلى الصفيف. هذا الأسلوب يعدل الصفيف.
المثال التالي ، إذا وصفته باللغة العادية ، سيبدو كما يلي: عليك ، في موضع الصفيف
1
، إزالة عناصر
0
وإضافة عنصر يحتوي على
b
.
let arr = ['a', 'c', 'd', 'e']; arr.splice(1, 0, 'b')
تُرجع الطريقة
slice()
نسخة ضحلة من الصفيف تحتوي على عناصرها ، بدءًا من موضع البداية المحدد وتنتهي بالموضع الذي يسبق موضع النهاية المحدد. إذا تم تحديد الموضع الأولي فقط عند الاتصال به ، فسيتم إرجاع الصفيف بأكمله ، بدءًا من هذا الموضع. هذا الأسلوب لا يعدل الصفيف. تقوم فقط بإرجاع جزء من هذه المجموعة الموصوفة عندما تم استدعائها.
let arr = ['a', 'b', 'c', 'd', 'e']; const sliced = arr.slice(2, 4); console.log(sliced);
▍ طريقة الفرز ()
تقوم طريقة
sort()
بفرز الصفيف وفقًا للشرط المحدد بواسطة الدالة التي تم تمريرها إليها. تأخذ هذه الوظيفة عنصرين من الصفيف (على سبيل المثال ، يمكن تمثيلهما كمعلمتين
a
و
b
) ، ومقارنتهما ، بإرجاع ، إذا لم تكن هناك حاجة إلى تبادل العناصر ، 0 إذا كانت
a
حاجة لوضعها في فهرس أقل من
b
هو رقم سالب ، وإذا كانت
b
بحاجة إلى وضع مؤشر أقل من الرقم الموجب.
let arr = [1, 7, 3, -1, 5, 7, 2]; const sorter = (firstEl, secondEl) => firstEl - secondEl; arr.sort(sorter); console.log(arr);
إذا كنت لا تستطيع تذكر هذه الطرق لأول مرة ، فتذكرها على ما يرام. الشيء الأكثر أهمية هو أن تعرف الآن ما يمكن أن تفعله مجموعة الصفيف القياسية. لذلك ، إذا لم تتذكر على الفور ميزات طريقة معينة ، فإن ما تعرفه عنها سيسمح لك بالعثور بسرعة على ما تحتاجه في الوثائق.
7. المولدات
يتم الإعلان عن مولدات JavaScript باستخدام حرف النجمة. إنها تسمح لك بتحديد القيمة التي سيتم إرجاعها في المرة
next()
تسمى فيها الطريقة
next()
. يمكن تصميم المولدات لإرجاع عدد محدود من القيم. إذا أعاد هذا المولد كل هذه القيم ، فستعود المكالمة
next()
إلى
next()
undefined
. يمكنك أيضًا إنشاء مولدات مصممة لإرجاع عدد غير محدود من القيم باستخدام الدورات.
هنا مولد مصمم لإرجاع عدد محدود من القيم:
function* greeter() { yield 'Hi'; yield 'How are you?'; yield 'Bye'; } const greet = greeter(); console.log(greet.next().value);
وهنا مولد مصمم لإرجاع عدد لا حصر له من القيم من خلال حلقة.
function* idCreator() { let i = 0; while (true) yield i++; } const ids = idCreator(); console.log(ids.next().value);
8. عوامل التحقق من المساواة (==) والمساواة الصارمة (===) من القيم
من المهم للغاية لأي مطور JS أن يفهم الفرق بين مشغلي المساواة (
==
) والمساواة الصارمة (
===
). الحقيقة هي أن المشغل
==
، قبل مقارنة القيم ، ينفذ عملية تحويل أنواعها (والتي يمكن أن تؤدي إلى عواقب غريبة ، للوهلة الأولى ،) ، وأن المشغل
===
لا يقوم بتحويل النوع.
console.log(0 == '0');
9. مقارنة الأشياء
يجب علي أحيانًا أن أرى كيف يرتكب الوافدون الجدد إلى برمجة JS نفس الخطأ. يحاولون مقارنة الكائنات مباشرة. تحتوي المتغيرات التي يتم "تخزين" الكائنات بها على مراجع إليها ، وليس هذه الكائنات نفسها.
لذلك ، على سبيل المثال ، في المثال التالي ، تبدو الكائنات كما هي ، ولكن عند مقارنتها مباشرةً ، نعلم أن الكائنات مختلفة ، حيث أن كل متغير من المتغيرات يحتوي على رابط لكائنه الخاص وهذه الارتباطات غير متساوية مع بعضها البعض.
const joe1 = { name: 'Joe' }; const joe2 = { name: 'Joe' }; console.log(joe1 === joe2);
علاوة على ذلك ، في المثال التالي ، اتضح أن
joe1
تساوي
joe2
لأن كلا المتغيرين
joe2
مرجعًا لنفس الكائن.
const joe1 = { name: 'Joe' }; const joe2 = joe1; console.log(joe1 === joe2);
إحدى طرق المقارنة بين الكائنات الحقيقية هي تحويلها الأولي إلى تنسيق سلسلة JSON. صحيح ، هذا النهج لديه مشكلة واحدة ، وهي أنه في تمثيل السلسلة التي تم الحصول عليها للكائن ، لا يمكن ضمان ترتيب معين لخصائصه. تتمثل الطريقة الأكثر موثوقية لمقارنة الكائنات في استخدام مكتبة خاصة تحتوي على أدوات للمقارنة العميقة للكائنات (على سبيل المثال ، هذه هي الطريقة
isEqual () لمكتبة
lodash ).
من أجل فهم تعقيدات مقارنة الكائنات بشكل أفضل وفهم العواقب المحتملة لكتابة روابط لنفس الكائنات في متغيرات مختلفة ، ألق نظرة على مفهوم JS الأول الذي تمت مناقشته في هذه المقالة.
10. وظائف رد الاتصال
وظائف رد الاتصال هي مفهوم جافا سكريبت بسيط إلى حد ما مع المبتدئين في بعض الأحيان صعوبة. النظر في المثال التالي. هنا ، يتم تمرير
myFunc()
تمامًا مثل ذلك - بدون أقواس) إلى
myFunc()
كدالة رد اتصال. تقوم هذه الوظيفة بتعيين مؤقت ، وبعد ذلك يتم استدعاء
myFunc()
ويتم عرض السلسلة التي تم تمريرها إلى
myFunc()
في وحدة التحكم.
function myFunc(text, callback) { setTimeout(function() { callback(text); }, 2000); } myFunc('Hello world!', console.log);
11. الوعود
بعد إتقان وظائف رد الاتصال والبدء في استخدامها في كل مكان ، سوف تجد نفسك قريبًا في ما يسمى "برد الاتصال الهاتفي". إذا كنت حقًا هناك - ألق نظرة على الوعود. يمكن لف الكود غير المتزامن بوعد ، وبعد تنفيذه بنجاح ، أخبر النظام عن الحل الناجح للوعد عن طريق استدعاء الطريقة المناسبة ، وإذا حدث خطأ ما - اطلب الطريقة التي تشير إلى هذا ورفض الوعد. لمعالجة النتائج التي يتم إرجاعها بواسطة الوعد ، استخدم الأسلوب
then()
، ولمعالجة الأخطاء ، استخدم أسلوب
catch()
.
const myPromise = new Promise(function(res, rej) { setTimeout(function(){ if (Math.random() < 0.9) { return res('Hooray!'); } return rej('Oh no!'); }, 1000); }); myPromise .then(function(data) { console.log('Success: ' + data); }) .catch(function(err) { console.log('Error: ' + err); });
12. متزامن / تنتظر البناء
بعد أن تتعهد بالوعود ، ربما ، ستحتاج إلى شيء أكثر. على سبيل المثال ، إتقان إنشاء المزامنة / الانتظار. إنه سكر نحوي للوعود. في المثال التالي ، نقوم بإنشاء ، باستخدام
async
غير المتزامنة ، دالة غير متزامنة ،
await
باستخدام الكلمة المفتاحية "
await
، ننظم الانتظار
greeter
الترحيب.
const greeter = new Promise((res, rej) => { setTimeout(() => res('Hello world!'), 2000); }) async function myFunc() { const greeting = await greeter; console.log(greeting); } myFunc();
ملخص
إذا كان ما تحدثنا عنه هنا في السابق غير مألوف لك ، فمن المرجح أنك ، على الأقل قليلاً ، قد نمت فوق نفسك من خلال قراءة هذا المقال. إذا لم تجد شيئًا جديدًا هنا ، فأود أن آمل أن تكون هذه المواد قد أتاحت لك الفرصة لممارسة وتعزيز معرفتك بـ JavaScript.
أعزائي القراء! ما هي مفاهيم JavaScript الأخرى التي تضيفها إلى هذا المقال؟
