مسار التحكّم هو ترتيب تنفيذ مترجم JavaScript. البيانات. إذا كان النص لا يتضمن عبارات تغير تدفقه، يتم تنفيذه من البداية إلى النهاية، سطرًا واحدًا في كل مرة. تُعد هياكل التحكم تُستخدم لتحديد ما إذا تم تنفيذ مجموعة من العبارات استنادًا إلى أو تنفيذ مجموعة من العبارات بشكل متكرر أو مقاطعة تسلسل العبارات.
العبارات الشرطية
تحدد العبارات الشرطية ما إذا كان يجب تنفيذ التعليمة البرمجية استنادًا إلى واحد أو
شروط أكثر. تنفذ العبارة الشرطية التعليمة البرمجية التي تحتوي عليها إذا كانت
يتم تقييم الشرط المرتبط (أو مجموعة من الشروط) بقيمة true
. بخلاف ذلك، سيتم
يتم تخطي هذا الرمز.
if
…else
تقيّم عبارة if
شرطًا داخل الأقواس المتطابقة التي
اتباعها. إذا تم تقييم الشرط داخل القوسين على true
،
عبارة أو عبارة حظر
يتم تنفيذ الأقواس المطابِقة التي تلي:
if ( true ) console.log( "True." );
> "True."
if ( true ) {
const myString = "True.";
console.log( myString );
}
> "True."
إذا تم تقييم الشرط داخل الأقواس إلى false
، فإن العبارة التي
يتبعه يتم تجاهله:
if ( false ) console.log( "True." );
كلمة رئيسية else
تتبع عبارة if
مباشرةً
تُحدد العبارة التي يتم تنفيذها بشكل مشروط العبارة المطلوب تنفيذها إذا كانت
يتم تقييم الشرط if
إلى false
:
if ( false ) console.log( "True." )''
else console.log( "False" );
> "False."
لربط عدة عبارات if
معًا، يمكنك
عبارة يتم تنفيذها بشكل مشروط بعد عبارة else
أخرى if
:
const myCondition = 2;
if ( myCondition === 5 ) console.log( "Five." );
else if ( myCondition === 2 ) console.log( "Two." );
ننصح بشدة باستخدام بنية عبارة الحظر التالية للشرطات من أجل
تحسِّن إمكانية القراءة، ولكن غالبًا ما تُستثنى من ذلك فقرات else if
:
if ( myCondition === 5 ) {
console.log( "Five." );
} else if ( myCondition === 3 ) {
console.log( "Three" );
} else {
console.log( "Neither five nor three." );
}
> "Neither five nor three."
عامل تشغيل ثلاثي
ينفذ if
عبارة بشكل مشروط. المشغل الثلاثي (بدقة أكبر
ولكنه أقل شيوعًا ويُسمى عامل التشغيل الشرطي الثلاثي) هو اختصار يستخدم
لتنفيذ تعبير بشكل مشروط. وكما يوحي الاسم، فالثلاثي
هو عامل JavaScript الوحيد الذي يستخدم ثلاثة معامِلات:
- شرط مطلوب تقييمه، متبوعًا بعلامة استفهام (
?
). - التعبير المطلوب تنفيذه إذا تم تقييم الشرط إلى
true
، متبوعًا نقطتان (:
). - التعبير المطلوب تنفيذه إذا تم تقييم الشرط إلى
false
.
يُستخدم هذا بشكل متكرر لتعيين قيمة أو تمريرها بشكل مشروط:
const myFirstResult = true ? "First value." : "Second value.";
const mySecondResult = false ? "First value." : "Second value.";
myFirstResult;
> "First value."
mySecondResult;
> "Second value."
switch
…case
استخدِم عبارة switch
لمقارنة قيمة تعبير بقائمة
القيم المحتملة المحددة باستخدام كلمة رئيسية واحدة أو أكثر من الكلمات الرئيسية case
. بناء الجملة هذا
غير معتاد لأنه يأتي من بعض القرارات السابقة المتعلقة بالتصميم في JavaScript.
switch
...تستخدم بنية case
الكلمة الرئيسية switch
، متبوعةً بتعبير
ملفوفة بين قوسين، متبوعة بزوج متطابق من الأقواس المعقوفة.
يمكن أن يحتوي النص الأساسي للسمة switch
على case
كلمة رئيسية، واحدة أو أكثر عادةً.
متبوعة بتعبير أو قيمة، متبوعة بنقطتين (:
).
عندما يصل المترجم الفوري إلى case
بقيمة تتطابق مع التعبير
يتم تقييمه بين القوسين بعد الكلمة الرئيسية switch
، فإنه ينفذ أي
العبارات التي تتّبع عبارة case
هذه:
switch ( 2 + 2 === 4 ) {
case false:
console.log( "False." );
case true:
console.log( "True." );
}
> "True."
يتم تنفيذ جميع العبارات التي تلي السمة case
المطابقة، حتى إذا كانت
مضمنة في عبارة حظر.
switch ( 2 + 2 === 4 ) {
case false:
console.log( "False." );
case true:
let myVariable = "True.";
console.log( myVariable );
}
> "True."
أحد مأزق استخدام switch…case
هو أنه بعد العثور على تطابق،
يُنفذ مترجم JavaScript أي عبارة تتبع case
المتطابق،
حتى تلك ضمن فقرات case
الأخرى. يسمى هذا "الخطأ" إلى
case
التالي:
switch ( 2 + 2 === 7 ) {
case false:
console.log( "False." );
case true:
console.log( "True." );
}
> "False."
> "True."
لمنع السقوط، يمكنك إنهاء كل حالة بالكلمة الرئيسية break
التي
تتوقف فورًا عن تقييم نص switch
:
switch ( 2 + 2 === 7 ) {
case false:
console.log( "False." );
break;
case true:
console.log( "True." );
break;
}
> "False."
إذا لم يتطابق أي من case
مع القيمة الشرطية، تختار switch
default
في حالة وجود واحدة:
switch ( 20 ) {
case 5:
console.log( "The value was five." );
break;
case 10:
console.log( "The value was ten." );
break;
default:
console.log( "The value was something unexpected." );
}
> "The value was something unexpected."
في المقابل، ينطبق السقوط على default
أيضًا، ما قد يؤدي إلى
نتائج غير متوقعة. لحلّ هذه المشكلة، يمكنك إنهاء عبارة default
باستخدام break
.
أو وضعه في النهاية في قائمة الحالات.
switch ( 20 ) {
default:
console.log( "The value was something unexpected." );
case 10:
console.log( "The value was ten." );
break;
case 5:
console.log( "The value was five." );
break;
}
> The value was something unexpected.
> The value was ten.
لأنّ فقرات case
لا تتطلب إدخال
عبارة الحظر للتجميع
لا يتم إنشاء جُمل متعددة وفقرات case
وdefault
النطاق المعجم في حد ذاته:
let myVariable;
switch ( true ) {
case true:
let myVariable = "True.";
break;
default:
let myVariable = "False.";
break;
}
> Uncaught SyntaxError: redeclaration of let myVariable
لإدارة النطاق، يمكنك استخدام عبارات الحظر:
let myVariable;
switch ( true ) {
case true: {
let myVariable = "True.";
break;
}
default: {
let myVariable = "False.";
break;
}
}
التكرارات الحلقية
تتيح لك التكرارات الحلقية تكرار مجموعة من العبارات طالما تم استيفاء الشرط، أو حتى يتم استيفاء أحد الشروط. استخدام التكرارات الحلقية لتنفيذ مجموعة من التعليمات عدد المرات، حتى يتم التوصل إلى نتيجة محددة، أو إلى أن ينتهي المُترجم إلى نهاية هيكل بيانات قابل للتكرار (على سبيل المثال، العنصر الأخير في مصفوفة أو خريطة أو مجموعة أو الخاصية الأخيرة لكائن أو الحرف الأخير في سلسلة).
التكرارات الحلقية تقاطع "من أعلى إلى أسفل" تنفيذ النص البرمجي من خلال التكرار على مجموعة من العبارات حتى يتم استيفاء شرط واحد أو أكثر، أو لا يتم اعتمادًا على بناء الجملة المستخدم لإنشاء التكرار الحلقي. بعد انتهاء التكرار الحلقي، وتنفيذه مستمرًا إلى العبارات التي تتبعه. في المثال التالي، يتم تنفيذ العبارات الموجودة في نص التكرار الحلقي ثلاث مرات قبل وينتقل المترجم الفوري إلى ما يلي:
let iterationCount = 0;
console.log( "Pre-loop." );
while( iterationCount < 3 ) {
iterationCount++;
console.log( "Loop iteration." );
}
console.log( "Continuing on." );
> "Pre-loop."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Continuing on."
إذا تعذّر استيفاء الشروط أثناء تنفيذ التكرار الحلقي، تستمر التكرار الحلقي. غير مسمى. تعتبر هذه الحلقات اللانهائية خطرًا شائعًا في البرمجة يمكن أن إلى سلسلة التنفيذ الرئيسية للإيقاف المؤقت إلى أجل غير مسمى أو حتى تعطيل علامة تبويب في المتصفح.
يتم تنفيذ المثال التالي طالما بقيت القيمة المنطقية true
true
ولأن القيم المنطقية غير قابلة للتغيير،
وهذا ينشئ تكرارًا لا نهائي.
console.log( "Pre-loop." );
while( true ) {
console.log( "Loop iteration." );
}
> "Pre-loop."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
…
تجنَّب ترك حلقات لانهائية في رمز الإنتاج. إذا قمت عن طريق الخطأ بإنشاء واحدة أثناء التطوير، يمكنك حلّ هذه المشكلة من خلال إغلاق علامة تبويب المتصفّح وتحديث التعليمة البرمجية بحيث لا تكون التكرار لانهائيًا، وإعادة فتح .
while
يتم إنشاء تكرار حلقي while
باستخدام الكلمة الرئيسية while
متبوعة بزوج من
الأقواس المتطابقة التي تحتوي على شرط يلزم تقييمه. إذا تم تحديد
يتم تقييمه بشكل مبدئي إلى true
، عبارة (أو
عبارة الحظر) التي تتبع
يتم تنفيذ هذين القوسين. وإذا لم يكن الأمر كذلك، فلن يتم تشغيل التكرار الحلقي أبدًا. بعد كل
التكرار، تتم إعادة تقييم الشرط، وإذا كانت لا تزال true
، يتم تنفيذ التكرار الحلقي
يتكرر.
let iterationCount = 0;
while( iterationCount < 3 ) {
iterationCount++;
console.log( `Loop ${ iterationCount }.` );
}
> "Loop 1."
> "Loop 2."
إذا عثر المترجم على عبارة continue
في حلقة while
، سيتم إيقافها.
التكرار ويعيد تقييم الشرط ويتابع التكرار الحلقي إن أمكن:
let iterationCount = 0;
while( iterationCount <= 5 ) {
iterationCount++;
if( iterationCount === 3 ) {
continue;
}
console.log( `Loop ${ iterationCount }.` );
}
console.log( "Loop ended." );
> "Loop 1."
> "Loop 2."
> "Loop 4."
> "Loop 5."
> "Loop ended."
إذا عثر المترجم على عبارة break
في حلقة while
، يعني ذلك تكرارًا.
ولا تتم إعادة تقييم الشرط، ما يسمح للمترجم الفوري بالمضي قدمًا:
let iterationCount = 1;
while( iterationCount <= 5 ) {
if( iterationCount === 3 ) {
console.log(`Iteration skipped.``);`
break;
}
console.log( `Loop ${ iterationCount }.` );
iterationCount++;
}
console.log( "Loop ended." );
> "Loop 1."
> "Loop 2."
> "Iteration skipped.
> "Loop ended."
يمكنك استخدام while
لتكرار عدد محدد من المرات، كما هو موضح في
المثال السابق، ولكن حالة الاستخدام الأكثر شيوعًا لـ while
هي تكرار حلقي
طول غير محدد:
let randomize = () => Math.floor( Math.random() * 10 );
let randomNum = randomize();
while( randomNum !== 3 ){
console.log( `The number is not ${ randomNum }.` );
randomNum = randomize();
}
console.log( `The correct number, ${ randomNum }, was found.` );
> "The number is not 0."
> "The number is not 6."
> "The number is not 1."
> "The number is not 8."
> "The correct number, 3, was found."
do
…while
do
...while
هي صيغة لحلقة while
التي يكون فيها الشرط الشرطي
التقييم في نهاية كل تكرار في التكرار الحلقي. وهذا يعني أن
يتم دائمًا تنفيذ نص التكرار الحلقي مرة واحدة على الأقل.
لإنشاء حلقة تكرار do
...while
، استخدِم الكلمة الرئيسية do
متبوعة بالعبارة
(أو عبارة الحظر) التي يجب
يتم تنفيذه في كل تكرار للتكرار الحلقي. بعد هذه العبارة مباشرةً، أضف
الدالة while
والأقواس المتطابقة التي تحتوي على الشرط المطلوب تقييمه. فعندما
لم يعد يتم تقييم هذا الشرط إلى true
، تنتهي التكرار الحلقي.
let iterationCount = 1;
do {
console.log( `Loop ${ iterationCount }.` );
iterationCount++;
} while ( iterationCount < 3 );
> "Loop 1."
> "Loop 2."
> "Loop 3."
كما هو الحال مع التكرار الحلقي while
، فإن حالة الاستخدام الأكثر شيوعًا لـ do
...while
هي حلقة
طول غير محدد:
let randomNum;
do {
randomNum = ( () => Math.floor( Math.random() * 10 ) )();
console.log( `Is the number ${ randomNum }?` );
} while ( randomNum !== 3 );
console.log( `Yes, ${ randomNum } was the correct number.` );
> "Is the number 9?"
> "Is the number 2?"
> "Is the number 8?"
> "Is the number 2?"
> "Is the number 3?"
> "Yes, 3 was the correct number."
for
يمكنك استخدام تكرارات for
لتكرار كمية معروفة. في قواعد التعليمات البرمجية القديمة، كان هذا
تُستخدم بشكل متكرر للتكرار على العناصر في الصفيفة.
لإنشاء حلقة تكرار for
، استخدِم الكلمة الرئيسية for
متبوعة بمجموعة من الأقواس
تقبل التعبيرات الثلاثة التالية بالترتيب وتفصل بينها
الفاصلة المنقوطة:
- تعبير سيتم تقييمه عند بدء التكرار الحلقي
- شرط يحدد ما إذا كان يجب استمرار التكرار الحلقي أم لا
- يشير هذا المصطلح إلى تعبير يتم تنفيذه في نهاية كل حلقة تكرار.
بعد هذين القوسين، أضف العبارة (عادةً عبارة حظر) أثناء التكرار الحلقي.
for( let i = 0; i < 3; i++ ) {
console.log( "This loop will run three times.")
}
يقوم التعبير الأول بإعداد متغير يعمل كعدّاد. هذا النمط
يتم تقييم التعبير مرة واحدة، قبل التكرار الأول للتكرار الحلقي. يمكنك
عليك إعداد هذا المتغيّر باستخدام let
(أو var
في السابق) مثل أي متغيّر آخر.
المتغير، ونطاقه هو نص التكرار الحلقي. يمكن أن يكون لهذه المتغيرات أي
مُعرفًا صالحًا، ولكن يُطلق عليها غالبًا i
للإشارة إلى "التكرار" أو "الفهرس".
يبدو أن هذا يتعارض مع
أفضل الممارسات المتعلّقة بأسماء المعرّفات التي يمكن توقّعها
ولكن هذا الاصطلاح جيد بما يكفي لتكون واضحة للمطورين الآخرين في
نظرة خاطفة. وبما أنّ المجموعات المفهرَسة لا تتم فهرستها،
لهذه المتغيرات غالبًا ما يكون لها القيمة الأولية 0
.
كما هو الحال مع أشكال التكرار الحلقي الأخرى، الشرط هو تعبير يحدد
ما إذا كان ينبغي تنفيذ التكرار الحلقي أم لا. غالبًا ما يتم استخدام هذا لتعيين
بـ عداد التكرار. يقيّم المترجم الفوري الحالة قبل
يتم تنفيذ حلقة for
للمرة الأولى.إذا لم يتم تنفيذ الشرط في البداية
لتقييمه إلى true
، فلن يتم تنفيذ نص التكرار الحلقي.
ويتم تنفيذ التعبير النهائي في نهاية كل تكرار عبر التكرار الحلقي. ويُستخدَم عادةً لزيادة المعرّف بمقدار واحد.
سترى غالبًا for
تكرارات في المصفوفات القديمة.
قواعد البيانات البرمجية. في هذه الحالات، يكون الشرط المحدد لاستمرار التكرار الحلقي هو
عدد التكرارات أقل من أو يساوي طول الصفيفة التي يتم تكرارها
عبر الإنترنت. يُستخدم المتغير المستخدم لتتبع عدد التكرارات الحالية للبحث
القيمة المرتبطة بهذا الفهرس في الصفيفة، مما يسمح لكل عنصر في
الصفيفة المطلوب التصرف عليها بالترتيب:
var myArray = [ true, false, true ];
for( let i = 0; i <= myArray.length; i++ ) {
console.log( myArray[ i ] );
}
> true
> false
> true
وقد لم يتم استخدام هذا النهج لصالح أساليب أكثر حداثة هياكل البيانات القابلة للتكرار.
for
[...] of
[...]
يمكنك استخدام حلقات for
...of
... لتكرار القيم المخزَّنة في
بنية بيانات قابلة للتكرار، مثل صفيف أو مجموعة أو خريطة
تستخدم حلقة التكرار for
...of
... الكلمة الرئيسية for
متبوعة بمجموعة من الأقواس
تحتوي على متغير، متبوعًا بـ of
، ثم يتم تكرار بنية البيانات
خلال. ويمكن أن يكون المتغير تصريحًا يتم تنفيذه هنا باستخدام let
أو const
أو
var
، وهو متغير تم الإعلان عنه سابقًا ضمن النطاق الحالي، وهو كائن
أو خاصية واحدة أو مثال
إتلاف المهمة.
يحتوي على قيمة العنصر التي تتجاوب مع التكرار الحالي
في الحلقة.
const myIterable = [ true, false, true ];
for( const myElement of myIterable ) {
console.log( myElement );
}
> true
> false
> true
في هذا المثال، يصلح استخدام const
لـ myElement
على الرغم من أنّ السمة myElement
هي
إعطاء قيمة جديدة في كل تكرار في التكرار الحلقي. هذا لأن المتغيرات
التي تم تعريفها باستخدام let
أو const
يتم تحديدها إلى عبارة الحظر ضمن
تكرار. يتم تهيئة المتغير في بداية كل تكرار، وإزالته عند
نهاية هذا التكرار.
for
... in
...
استخدام التكرارات الحلقية for
...in
... لتكرار الخصائص القابلة للتعداد لعنصر،
بما في ذلك الخصائص المكتسَبة القابلة للتعداد. كما هو الحال مع التكرار الحلقي for
...of
...، فإن
for
...in
... تستخدم حلقة التكرار الكلمة الرئيسية for
متبوعة بمجموعة من الأقواس
يحتوي على متغير يشتمل على قيمة مفتاح الخصائص المقابلة
مع التكرار الحالي للتكرار الحلقي. ويتبع هذا المتغير
كلمة رئيسية واحدة (in
)، ثم يتم تكرار العنصر على:
const myObject = { "myProperty" : true, "mySecondProperty" : false };
for( const myKey in myObject ) {
console.log( myKey );
}
> "myProperty"
> "mySecondProperty"
مجددًا، وعلى الرغم من تغيير قيمة myKey
مع كل تكرار في التكرار الحلقي،
يمكنك استخدام const
بدون خطأ لأنه يتم تجاهل المتغير بشكل فعّال
في نهاية كل تكرار، ثم إعادة إنشائه في البداية.
لا تتوفر القيمة المرتبطة بكل مفتاح خاصية مباشرةً
بنية for
...in
... ومع ذلك، نظرًا لأن التكرار الحلقي لديها إمكانية الوصول إلى مفتاح الخاصية في
كل تكرار، يمكنك استخدام هذا المفتاح "للبحث" وقيمتها:
const myObject = { "myProperty" : true, "mySecondProperty" : false };
for( const myKey in myObject ) {
const myValue = myObject[ myKey ];
console.log( `${ myKey } : ${ myValue }` );
}
> "myProperty : true"
> "mySecondProperty : false"
إن الخصائص المكتسَبة من الصيغ المضمنة غير قابلة للتعداد، مما يعني أن
لا يتم تكرار for
...in
... من خلال المواقع الإلكترونية المكتسَبة من Object
.
الدالة الإنشائية. ومع ذلك، فإن أي خصائص يمكن تعدادها في تصنيف
يتم تضمين سلسلة النموذج الأوّلي:
const myPrototype = { "protoProperty" : true };
const myObject = Object.create( myPrototype, {
myProperty: {
value: true,
enumerable: true
}
});
for ( const myKey in myObject ) {
const myValue = myObject[ myKey ];
console.log( `${ myKey } : ${ myValue }` );
}
> "myProperty : true"
> "protoProperty : true"
توفر لغة JavaScript طرقًا مضمنة لتحديد ما إذا كان الموقع عبارة
خاصية مباشرة للكائن بدلاً من خاصية على النموذج الأولي للكائن
سلسلة: modern
Object.hasOwn()
وطريقة Object.prototype.hasOwnProperty()
القديمة هذه
لتقييم ما إذا كانت خاصية محددة موروثة (أو غير معرَّفة)
عرض true
فقط للخصائص المباشرة لكائن محدد:
const myPrototype = { "protoProperty" : true };
const myObject = Object.create( myPrototype, {
myProperty: {
value: true,
enumerable: true
}
});
for ( const myKey in myObject ) {
const myValue = myObject[ myKey ];
if ( Object.hasOwn( myObject, myKey ) ) {
console.log( `${ myKey } : ${ myValue }` );
}
}
> "myProperty : true"
هناك أيضًا ثلاث طرق ثابتة تقوم كل منها بإرجاع مصفوفة مكونة من
مفاتيح عنصر يمكن تعداده (Object.keys()
) أو القيم (Object.values()
)
أزواج المفتاح/القيمة (Object.entries()
):
const myObject = { "myProperty" : true, "mySecondProperty" : false };
Object.keys( myObject );
> Array [ "myProperty", "mySecondProperty" ]
يتيح لك هذا التكرار التحسيني لمفاتيح الكائن أو القيم أو أزواج المفتاح/القيمة (باستخدام مهمة إتلافها) بدون تضمين الخصائص التي يملكها النموذج الأوّلي لهذا الكائن:
const myPrototype = { "protoProperty" : "Non-enumerable property value." };
const myObject = Object.create( myPrototype, {
myProperty: {
value: "Enumerable property value.",
enumerable: true
}
});
for ( const propKey of Object.keys( myObject ) ) {
console.log( propKey );
}
> "myProperty"
for ( const propValue of Object.values( myObject ) ) {
console.log( propValue );
}
> "Enumerable property value."
for ( const [ propKey, propValue ] of Object.entries( myObject ) ) {
console.log( `${ propKey } : ${ propValue }` );
}
> "myProperty : Enumerable property value."
forEach()
طرق forEach()
التي توفرها المصفوفة،
خريطة، ضبط،
توفر دوال إنشاء NodeList اختصارًا مفيدًا للتكرار في البيانات
في سياق دالة استدعاء. على عكس الأشكال الأخرى للتكرار الحلقي،
لا يمكن مقاطعة التكرار الذي تم إنشاؤه بأي طريقة forEach()
باستخدام break
أو
continue
forEach
هي طريقة يملكها النموذج الأولي لكل هيكل بيانات. كل forEach
تتوقع دالة رد الاتصال كوسيطة، على الرغم من أنها تختلف قليلاً في
مصطلحات الوسيطات المضمنة عند استدعاء هذه الدالة. والثانية، اختيارية
تحدّد الوسيطة قيمة this
لاستخدامها كسياق استدعاء
.
توفر دالة رد الاتصال المستخدمة مع Array.forEach
معلمات تحتوي على
قيمة العنصر الحالي وفهرس العنصر الحالي والمصفوفة التي تم استدعاء طريقة forEach
عليها:
const myArray = [ true, false ];
myArray.forEach( ( myElement, i, originalArray ) => {
console.log( i, myElement, originalArray );
});
> 0 true Array(3) [ true, false ]
> 1 false Array(3) [ true, false ]
توفر دالة رد الاتصال المستخدمة مع Map.forEach
معلمات تحتوي على
القيمة المرتبطة بالعنصر الحالي، وهو المفتاح المرتبط بقيمة
والخريطة التي تم استدعاء طريقة forEach
عليها:
const myMap = new Map([
['myKey', true],
['mySecondKey', false ],
]);
myMap.forEach( ( myValue, myKey, originalMap ) => {
console.log( myValue, myKey, originalMap );
});
> true "myKey" Map { myKey → true, mySecondKey → false }
> false "mySecondKey" Map { myKey → true, mySecondKey → false }
تتضمّن معاودة الاتصال Set.forEach
معلَمات مشابهة. نظرًا لأن تعيين لا يحتوي على
الفهارس أو المفاتيح المميزة عن القيم، تقدم الوسيطة الثانية بدلاً من ذلك
قيمة زائدة يمكن تجاهلها، بشكل صارم للحفاظ على اتساق بناء الجملة مع
طرق forEach
الأخرى.
const mySet = new Set([ true, false ]);
mySet.forEach( ( myValue, myKey, originalSet ) => {
console.log( myValue, myKey, originalSet );
});
> true true Set [ true, false ]
> false false Set [ true, false ]
المكرّرات
السمة القابلة للتكرار هي أي بنية بيانات تتكوّن من عناصر فردية يمكن
وتكراره باستخدام النُهُج المذكورة سابقًا. إنّ المحسّن هو
كائن قابل للتكرار يتبع بروتوكول التكرار، مما يعني أنه ينبغي تنفيذه
طريقة next()
تمر عبر العناصر التي تحتوي عليها واحدًا تلو الآخر،
في كل مرة يتم فيها استدعاء هذه الطريقة، مع عرض كائن لكل تسلسل
بتنسيق محدد.
هياكل البيانات المضمنة القابلة للتكرار في JavaScript (مثل
مصفوفة،
خريطة
Set) ليست مكررات في و من
ولكنهم جميعًا تكتسبون طريقة iterator
، ويمكن الوصول إليها باستخدام
@@iterator
رمز معروف،
الأمر الذي يُرجع كائن مكرر تم إنشاؤه من هيكل البيانات القابلة للتكرار:
const myIterable = [ 1, 2, 3 ];
const myIterator = myIterable[ Symbol.iterator ]();
myIterable;
> (3) [1, 2, 3]
myIterator;
> Array Iterator {}
يؤدي استدعاء الطريقة next()
في مكرر إلى خطوات بين العناصر التي تدخلها.
يحتوي على واحد تلو الآخر، بحيث تعرض كل استدعاء كائنًا يحتوي على اثنين
الخصائص: value
، الذي يحتوي على قيمة العنصر الحالي،
done
، وهي قيمة منطقية تخبرنا ما إذا كان المكرر قد تجاوز العنصر الأخير في
هيكل البيانات. تكون قيمة done
هي true
فقط عند إجراء مكالمة إلى next()
.
إلى محاولة الوصول إلى عنصر ما بعد العنصر الأخير في
والمكرر.
const myIterable = [ 1, 2, 3 ];
const myIterator = myIterable[ Symbol.iterator ]();
myIterator.next();
> Object { value: 1, done: false }
myIterator.next();
> Object { value: 2, done: false }
myIterator.next();
> Object { value: 3, done: false }
myIterator.next();
> Object { value: undefined, done: true }
وظائف المنشئ
استخدام الكلمة الرئيسية function*
(مع وضع علامة النجمة) للإعلان عن منشئ
أو تحديد تعبير دالة المنشئ:
function* myGeneratorFunction() { };
كما هي الحال مع المحسّنات، تحافظ دوال المنشئ على الحالة نفسها. الاتصال بـ تُرجع دالة المنشئ كائن منشئ جديد ولكنها لا تُحدث على الفور لتنفيذ التعليمة البرمجية في نص الدالة:
function* myGeneratorFunction() {
console.log( "Generator function body ")
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject;
> Generator { }
typeof myGeneratorObject;
> "object"
تتبع كائنات المنشئ بروتوكول المكرر. قيمة كل استدعاء
يُحدد next()
في نتائج الدالة المنشئ من خلال تعبير yield
،
التي توقف تنفيذ دالة المنشئ مؤقتًا وتُرجع قيمة
تعبير يحتوي على الكلمة الرئيسية yield
. المكالمات اللاحقة على الرقم next()
مواصلة تنفيذ الدالة، مع الإيقاف المؤقت عند تعبير yield
التالي
بإرجاع القيمة المرتبطة.
function* myGeneratorFunction() {
yield "My first yielded value.";
yield "My second yielded value.";
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject.next();
> Object { value: "My first yielded value.", done: false }
myGeneratorObject.next();
> Object { value: "My second yielded value.", done: false }
عند استدعاء next()
بعد عدم تحديد قيم إضافية باستخدام yield
،
return
أو throw
(في حالة حدوث خطأ)، والباقي من الدالة
تنفيذ النص الأساسي، ويحتوي الكائن المعروض على value
من undefined
وdone
خاصية true
:
function* myGeneratorFunction() {
console.log( "Start of the generator function." );
yield "First";
console.log( "Second part of the generator function." );
yield "Second";
console.log( "Third part of the generator function." );
yield "Third";
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject.next();
> "Start of the generator function."
> Object { value: "First", done: false }
myGeneratorObject.next();
> "Second part of the generator function."
> Object { value: "Second", done: false }
myGeneratorObject.next();
> "Third part of the generator function."
> Object { value: "Third", done: false }
myGeneratorObject.next();
> Object { value: undefined, done: true }
استخدِم next()
فقط على الكائن الذي تعرضه دالة المنشئ، وليس
المولد نفسه. وإلا، فإن كل استدعاء لدالة منشئ
تنشئ كائن منشئ جديد:
function* myGeneratorFunction() {
yield "First";
yield "Second";
};
myGeneratorFunction().next();
> Object { value: "First", done: false }
myGeneratorFunction().next();
> Object { value: "First", done: false }
كما هي الحال مع أي دالة، تتوقف دالة المنشئ عندما يصادفها return
. ثم تُرجع كائنًا إلى سياق الاستدعاء الذي يحتوي على
القيمة التي تم إرجاعها والسمة done
بالقيمة true
.
function* myGeneratorFunction() {
yield 1;
yield 2;
return 3;
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject.next().done;
> Object { value: 1, done: false }
myGeneratorObject.next().done;
> Object { value: 2, done: false }
myGeneratorObject.next();
> Object { value: 3, done: true }
ويمكن أن يأخذ تعبير yield
بعض دلالات المعرّف،
السماح "بالتواصل" ثنائي الاتجاه من وإلى الجزء المعلق من
المستخدم العادي. عند تمرير قيمة إلى طريقة next()
للمنشئ
وسيطة، تستبدل القيمة المرتبطة بالسابق، معلقة
تعبير yield
:
function* myGeneratorFunction() {
const firstYield = yield;
yield firstYield + 10;
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject.next();
> Object { value: undefined, done: false }
myGeneratorObject.next( 5 );
> Object { value: 15, done: false }
ضع في اعتبارك أن ذلك يستبدل التعبير الكامل المرتبط
yield
السابقة، ولا تتم فقط إعادة تعيين قيمة yield
السابقة إلى
القيمة المحددة في next()
:
function* myGeneratorFunction() {
const firstYield = yield;
const secondYield = yield firstYield + 100;
yield secondYield + 10;
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject.next();
> Object { value: undefined, done: false }
myGeneratorObject.next( 10 ); // Can be thought of as changing the value of the `firstYield` variable to `10
> Object { value: 110, done: false }
myGeneratorObject.next( 20 ); // Can be thought of as changing the value of the `secondYield` variable to `20`, _not_ `20 + 100;`
> Object { value: 30, done: false }
يتم تجاهل أي وسيطة تم تمريرها إلى الاستدعاء الأول إلى next()
، نظرًا لعدم وجود
تعبير yield
السابق لقبول هذه القيمة. وكما هو الحال مع أي دالة أخرى،
تكون الوسيطات التي تم تمريرها إلى استدعاء دالة المنشئ الأولي متاحة طوال
نطاق نص دالة المنشئ:
function* myGeneratorFunction( startingValue ) {
let newValue = yield startingValue + 1;
newValue = yield newValue + 10;
yield startingValue + 20;
};
const myGeneratorObject = myGeneratorFunction( 2 );
myGeneratorObject.next( 1 );
> Object { value: 3, done: false }
myGeneratorObject.next( 5 );
> Object { value: 15, done: false }
myGeneratorObject.next( 10 );
Object { value: 22, done: false }
يُستخدم عامل التشغيل yield*
(لاحظ علامة النجمة) مع عامل تشغيل قابل للتكرار، مثل
دالة منشئ أخرى، لتكرار كل قيمة في المعامل الخاص بها
العائد:
function* mySecondaryGenerator() {
yield 2;
yield 3;
}
function* myGenerator() {
yield 1;
yield* mySecondaryGenerator();
yield 4;
return 5;
}
const myIterator = myGenerator();
myIterator.next();
> Object { value: 1, done: false }
myIterator.next();
> Object { value: 2, done: false }
myIterator.next();
> Object { value: 3, done: false }
myIterator.next();
> Object { value: 4, done: false }
myIterator.next();
> Object { value: 5, done: true }
JavaScript غير متزامن
على الرغم من أنّ JavaScript متزامن في الأساس بشكل عام، إلا أن هناك آليات تتيح للمطورين الاستفادة من حلقة الحدث لتنفيذ المهام غير المتزامنة.
الوعود
الوعد هو عنصر نائب لقيمة لا معروفة عندما يكون الوعد إنشاء. وهي عبارة عن حاوية تمثل عملية غير متزامنة، ويمكن أن تشير المصطلحات التي تعتبرها العملية ناجحة أو فاشلة، فإن الإجراءات التي يجب اتخاذها في كلتا الحالتين، والقيمة الناتجة.
إنشاء مثيل وعود باستخدام عامل التشغيل new
مع عنصر Promise
المدمَج
الدالة الإنشائية. تقبل دالة الإنشاء هذه دالة تُسمى executor.
كوسيطة. تُستخدم دالة التنفيذ هذه عادةً لتنفيذ إجراء واحد أو أكثر
إجراءات غير متزامنة، ثم قم بإملاء الشروط التي يجب أن يكون الوعد من خلالها
تم اعتبارها قد تم تلبيتها أو رفضها بنجاح. يتم تعريف الوعد على أنّه في انتظار المراجعة.
أثناء تشغيل دالة التنفيذ. بعد انتهاء القائم بالتنفيذ، يتم إنشاء وعد
تُعتبر مُمتثلة (أو تم حلّها في بعض مصادر الوثائق) إذا
اكتمال دالة التنفيذ والإجراء غير المتزامن الذي ينفذه
بنجاح، ورفضه إذا واجهت دالة التنفيذ خطأ، أو
فشل الإجراء غير المتزامن الذي يتم تنفيذه. بعد الوفاء بالوعد أو
مرفوضًا، فسيتم اعتباره تمت تسويته.
const myPromise = new Promise( () => { });
تستدعي الدالة الإنشائية دالة التنفيذ باستخدام وسيطتين. تلك الوسيطات هي وظائف تتيح لك الوفاء بالوعد أو رفضه يدويًا:
const myPromise = new Promise( ( fulfill, reject ) => { });
يتم استدعاء الدوال المستخدمة للوفاء بالوعد أو رفضه مع قيمة الوعد كوسيطة (عادةً ما يكون خطأ للرفض):
const myPromise = new Promise( ( fulfill, reject ) => {
const myResult = true;
setTimeout(() => {
if( myResult === true ) {
fulfill( "This Promise was successful." );
} else {
reject( new Error( "This Promise has been rejected." ) );
}
}, 10000);
});
myPromise;
> Promise { <state>: "pending" }
myPromise;
> Promise { <state>: "fulfilled", <value>: "This Promise was successful." }
سلسلة التعهد
ويمكن اتخاذ إجراء بشأن عنصر Promise الناتج باستخدام then()
وcatch()
finally()
طريقة مكتسَبة من الدالة الإنشائية للوعد كل من هذه
تُرجع وعدًا يمكن التعامل معه على الفور باستخدام then()
،
catch()
، أو finally()
مرة أخرى، ما يتيح لك سلسلة الوعود الناتجة.
توفّر then()
دالتَي استدعاء كوسيطات. استخدام الخيار الأول لاستيفاء
والوعد الناتج، والثاني يرفضه. تقبل كلتا الطريقتين
التي تعطي الوعد الناتج قيمته.
const myPromise = new Promise( ( fulfill, reject ) => {
const myResult = true;
setTimeout(() => {
if( myResult === true ) {
fulfill( "This Promise was fulfilled." );
} else {
reject( new Error( "This Promise has been rejected." ) );
}
}, 100);
});
myPromise.then( successfulResult => console.log( successfulResult ), failedResult => console.error( failedResult ) );
> "This Promise was successful."
يمكنك أيضًا استخدام السمة then()
للتعامل مع حالة التنفيذ فقط، وcatch
لتنفيذ ما يلي:
التعامل مع حالة الرفض. يمكنك استدعاء الدالة catch
مع وسيطة واحدة تحتوي على
القيمة المقدمة في طريقة رفض الوعد:
const myPromise = new Promise( ( fulfill, reject ) => {
const myResult = false;
setTimeout(() => {
if( myResult === true ) {
fulfill( "This Promise was fulfilled." );
} else {
reject( new Error( "This Promise has been rejected." ) );
}
}, 100);
});
myPromise
.then( fulfilledResult => console.log(fulfilledResult ) )
.catch( rejectedResult => console.log( rejectedResult ) )
.finally( () => console.log( "The Promise has settled." ) );
> "Error: This Promise has been rejected."
> "The Promise has settled."
على عكس then
وcatch
، اللذان يسمحان بتشغيل وظيفة معالِج عند إدخال وعد
تم تنفيذ أو رفض دالة، تم تمرير دالة كوسيطة إلى finally
بغض النظر عما إذا تم الوفاء بالوعد أو رفضه.
يتم استدعاء دالة المعالج بدون وسيطات، لأنها غير مخصصة
تعمل بالقيم التي تم تمريرها من Promise، إلا لتنفيذ التعليمة البرمجية بعد
لقد اكتمل الوعد.
التزامن
يوفر دالة إنشاء الوعد أربع طرق للعمل مع العديد من
تقديم وعود باستخدام نموذج قابل للتكرار يحتوي على كائنات التعهد هذه
طرق إرجاع كل منها للوعد، والذي يتم الوفاء به أو رفضه استنادًا إلى الحالة
بالوعود التي تم تمريرها إليه. على سبيل المثال، ينشئ Promise.all()
وعدًا
يتم الوفاء به فقط في حال الوفاء بكل وعد تم تمريره إلى هذه الطريقة:
const firstPromise = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const secondPromise = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const thirdPromise = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const failedPromise = new Promise( ( fulfill, reject ) => reject( "Failed.") );
const successfulPromises = [ firstPromise, secondPromise, thirdPromise ];
const oneFailedPromise = [ failedPromise, ...successfulPromises ];
Promise.all( successfulPromises )
.then( ( allValues ) => {
console.log( allValues );
})
.catch( ( failValue ) => {
console.error( failValue );
});
> Array(3) [ "Successful. ", "Successful. ", "Successful. " ]
Promise.all( oneFailedPromise )
.then( ( allValues ) => {
console.log( allValues );
})
.catch( ( failValue ) => {
console.error( failValue );
});
> "Failed."
في ما يلي طُرق التزامن الواعدة:
Promise.all()
- لا يتم استيفاء هذا الشرط إلا في حال الوفاء بجميع الوعود المقدّمة.
Promise.any()
- تتمّ الوفاء بأيّ من الوعود المقدّمة ورفضها فقط في حال رفض جميع التعهدات
Promise.allSettled()
- يتم الوفاء بالوعود بعد قبولها، بغض النظر عن النتيجة.
Promise.race()
- رفض "الوعد" أو الوفاء به بناءً على نتيجة الوعد الأول بالتسوية ويتجاهل جميع الوعود التي تمت تسويتها لاحقًا.
async
/await
عند استخدام الكلمة الرئيسية async
قبل بيان دالة
أو تعبير الدالة، أي
تُعرَض القيمة التي تعرضها الدالة على أنّها وعد تم الوفاء به يحتوي على
ويسمح لك هذا بتشغيل العمليات غير المتزامنة وإدارتها باستخدام
وسير العمل كتطوير متزامن.
async function myFunction() {
return "This is my returned value.";
}
myFunction().then( myReturnedValue => console.log( myReturnedValue ) );
> "This is my returned value."
يوقف التعبير await
تنفيذ دالة غير متزامنة مؤقتًا بينما
تتم تسوية الوعد المرتبط. بعد تسوية الوعد، قيمة
التعبير await
هو قيمة الوعد التي تم تنفيذها أو رفضها.
async function myFunction() {
const myPromise = new Promise( ( fulfill, reject ) => { setTimeout( () => fulfill( "Successful. "), 5000 ); });
const myPromisedResult = await myPromise;
return myPromisedResult;
}
myFunction()
.then( myResult => console.log( myResult ) )
.catch( myFailedResult => console.error( myFailedResult ) );
> "Successful."
ويتم عرض أي قيمة غير واعدة مضمّنة في تعبير await
على أنّها
الوفاء بالوعد:
async function myFunction() {
const myPromisedResult = await "String value.";
return myPromisedResult;
}
myFunction()
.then( myResult => console.log( myResult ) )
.catch( myFailedResult => console.error( myFailedResult ) );
> "String value."
التحقق من فهمك
ما نوع التكرار الحلقي الذي تستخدمه للتكرار على كمية معروفة؟
for
while
do...while