
يشير التكرار إلى عملية استخراج البيانات بشكل مستمر من مجموعة بيانات بترتيب معين.
إذن ما الفرق بين التكرار والاجتياز؟
في JavaScript، المكرِّر هو كائن يمكنه استدعاء الطريقة next لتنفيذ التكرار إرجاع كائن بخاصيتين.
value : القيمة التالية للكائن القابل للتكرارdone تشير إلى ما إذا كان قد تم استرداد جميع البيانات. false يعني أنه لا تزال هناك بيانات، true " يعني أنه لا توجد بيانات لاحقًا.لإنشاء مكررات من خلال وظيفة مصنع التكرار، Symbol.iterator في الكائن القابل للتكرار.
const arr = []console.log(arr)

ثابت آر = [1، 2، 3]
const iter1 = arr[Symbol.iterator]() // أنشئ مكررًا من خلال وظيفة مصنع التكرار `Symbol.iterator`.
console.log(iter1)
console.log(iter1.next())
console.log(iter1.next())
console.log(iter1.next())
console.log(iter1.next())
console.log('%c%s', 'color:red;font-size:24px;', '================')
const mymap = خريطة جديدة ()
mymap.set('name', 'clz')
mymap.set('age', 21)
const iter2 = mymap[Symbol.iterator]() // أنشئ مكررًا من خلال وظيفة مصنع التكرار `Symbol.iterator`.
console.log(iter2)
console.log(iter2.next())
console.log(iter2.next())
console.log(iter2.next())
يمكن العثور على أن المكرر يكتمل بعد أخذ القيمة الأخيرة، أي عندما تكون value التالية للمكرر undefined .
ومع ذلك، فإن البيان أعلاه ليس دقيقًا جدًا، ولا يكتمل عندما تكون value التالية للمكرر undefined . تحتاج أيضًا إلى تحديد ما إذا كانت هناك قيمة بالفعل أم لا، أو ما إذا كانت هناك قيمة undefined في الكائن القابل للتكرار. إذا كانت هناك قيمة undefined في الكائن القابل للتكرار، فلن تكتمل في هذا الوقت.
ثابت آر = [1، 2، 3، غير محدد] const iter1 = arr[Symbol.iterator]() // أنشئ مكررًا من خلال وظيفة مصنع التكرار `Symbol.iterator`. console.log(iter1) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next())

استدعاء وظيفة مصنع التكرار عدة مرات دون التدخل في بعضها البعض لإنشاء عدة مكررات يمثل اجتيازًا مرتبًا لمرة واحدة للكائن القابل للتكرار. لا تتداخل التكرارات المختلفة مع بعضها البعض وسوف تعبر فقط الكائنات القابلة للتكرار بشكل مستقل .
ثابت آر = [1، 2، 3]
const iter1 = arr[Symbol.iterator]() // أنشئ مكررًا من خلال وظيفة مصنع التكرار `Symbol.iterator`.
const iter2 = arr[Symbol.iterator]()
console.log('Iterator1:', iter1.next())
console.log('Iterator2:', iter2.next())
console.log('Iterator1:', iter1.next())
console.log('Iterator2:', iter2.next())
const arr = [1, 2, 3]
const iter = arr[Symbol.iterator]()
لـ (const i of iter) {
console.log(i) // الإخراج 1، 2، 3 بالتسلسل
} إذا تم تعديل الكائن القابل للتكرار أثناء التكرار، فسيتم أيضًا تعديل النتيجة التي حصل عليها المكرِّر.
ثابت آر = [1، 2، 3] console.log(arr) const iter = arr[Symbol.iterator]() console.log(iter.next()) آر [1] = 999 console.log(iter.next()) console.log(iter.next())

عندما نكرر done: true ، هل سيتم الإبلاغ عن خطأ عند الاتصال next أم لن يتم إرجاع أي شيء؟
ومع ذلك، لا، سيكون المكرِّر في حالة مكتملة ولكن غير مكتملة done: true يعني أنه قد اكتمل، ولكن لا يزال من الممكن استدعاء next في المستقبل، على الرغم من أن النتيجة ستكون دائمًا { value: undefined, done: true } . ولهذا السبب يقال أنه تم القيام به ولكن لم يتم القيام به .
ثابت آر = [1، 2، 3] const iter = arr[Symbol.iterator]() console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next())

من المثال أعلاه، يمكننا أن نعرف أن المكرر يتم إنشاؤه من خلال وظيفة مصنع المكرر، Symbol.iterator iterator ، لذلك نحن بحاجة إلى تنفيذ وظيفة مصنع مكرر، وبعد ذلك يمكن للمكرر استدعاء الطريقة next ، لذلك تحتاج أيضًا إلى قم بتنفيذ الطريقة next ، أما بالنسبة لوظيفة مصنع التكرار، فإنها تقوم في الواقع بإرجاع this مباشرة.
مثال العداد:
عداد الفئة {
منشئ (الحد) {
هذا العدد = 1
this.limit = الحد }
التالي() {
إذا (هذا. العد <= هذا. الحد) {
يعود {
تم: كاذب،
القيمة: this.count++
}
} آخر {
العودة { تم: صحيح، القيمة: غير محددة }
}
}
[Symbol.iterator]() {
إرجاع هذا
}} عداد ثابت = عداد جديد (3) const iter = عداد[Symbol.iterator]() console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next())

للوهلة الأولى، لا توجد مشكلة، ولكن إذا استخدمنا for-of للتجول، فيمكننا العثور على المشكلة.
عداد ثابت = عداد جديد (3) لـ (دع i من العداد) {
console.log(i)}console.log('تكرار آخر:')for (let i of counter) {
console.log(i)}
كما أن استخدام حلقة for-of يجعلها قابلة للتصرف أيضًا. وذلك لأن count هو متغير في هذا المثال، لذلك يتم استخدام نفس المتغير في كلا التكرارات، ومع ذلك، بعد الحلقة الأولى للمتغير، فقد تجاوز الحد، لذلك لن تحصل على أي شيء باستخدام حلقة for-of . مرة أخرى كانت النتيجة.
يمكنك وضع متغير count في الإغلاق، ثم إرجاع المكرر خلال الإغلاق، بحيث يتوافق كل مكرر تم إنشاؤه مع عداد جديد.
عداد الفئة {
منشئ (الحد) {
this.limit = الحد }
[Symbol.iterator]() {
دعونا العد = 1
حد ثابت = this.limit return {
// يجب أن تقوم وظيفة مصنع التكرار بإرجاع كائن بالطريقة التالية، لأن التكرار يتم تنفيذه فعليًا عن طريق استدعاء الطريقة التالية next() {
إذا (العدد <= الحد) {
يعود {
تم: كاذب،
القيمة: العد ++
}
} آخر {
العودة { تم: صحيح، القيمة: غير محددة }
}
}
}
}} اختبار
const counter = new Counter(3)for (let i of counter) {
console.log(i)}console.log('تكرار آخر:')for (let i of counter) {
console.log(i)}
يشبه تمامًا استخدام حلقة for-of ، وسيقوم المكرر باستدعاء الطريقة next بذكاء. عندما ينتهي المكرر مبكرًا، فإنه سيستدعي أيضًا طريقة return .
[Symbol.iterator]() {
دعونا العد = 1
حد ثابت = this.limit return {
// يجب أن تقوم وظيفة مصنع التكرار بإرجاع كائن بالطريقة التالية، لأن التكرار يتم تنفيذه فعليًا عن طريق استدعاء الطريقة التالية next() {
إذا (العدد <= الحد) {
يعود {
تم: كاذب،
القيمة: العد ++
}
} آخر {
العودة { تم: صحيح، القيمة: غير محددة }
}
},
يعود() {
console.log("إنهاء المكرر مبكرًا")
العودة { تم: صحيح }
}
}} اختبار
const counter = new Counter(5)for (let i of counter) {
إذا (ط === 3) {
استراحة؛
}
console.log(i)}
إذا لم يكن المكرِّر مغلقًا، فيمكنك متابعة التكرار من حيث توقفت . لا يمكن إغلاق مكررات المصفوفة.
const arr = [1, 2, 3, 4, 5]const iter = arr[Symbol.iterator]()iter.return = function () {
console.log("الخروج من المكرِّر مبكرًا")
يعود {
تم: صحيح
}}لـ (const i of iter) {
console.log(i)
إذا (ط === 2) {
استراحة
}}لـ (const i of iter) {
console.log(i)}