Symbol.iterator في جافا سكريبت

هذه مقالة قصيرة ولكنها مفيدة للمطورين في المستقبل على متكررة Javascript.


صورة


قبل أن نتعرف على التكرارات في js ، تذكر ما هو الرمز :


الرمز هو معرف فريد وغير قابل للتغيير. تم إنشاؤه باستخدام وظيفة Symbol () ، ويمكن أيضًا تسميته Symbol ('foo'). لا تتساوى الرموز التي تحمل نفس التصنيفات مع بعضها البعض ، وبشكل عام ، لا تساوي أي رموز بعضها البعض (تذكر التفرد).

هناك رموز النظام مثل Symbol.iterator و Symbol.toPrimitive وغيرها. يتم استخدام أحرف النظام من قبل اللغة نفسها ، ولكن يمكننا أيضًا استخدامها لتغيير السلوك الافتراضي لبعض الكائنات.


الرموز هي جزء من مواصفات es6 ، لذلك فهي غير مدعومة في أي ، على الإطلاق ( caniuse ).


حول Symbol.iterator


بشكل أساسي ، يتم استخدام هذا الرمز من قبل اللغة في for for of loop عند التكرار على خصائص كائن. يمكن استخدامه أيضًا مباشرة مع أنواع البيانات المدمجة:


const rangeIterator = '0123456789'[Symbol.iterator](); console.log(rangeIterator.next()); // {value: "0", done: false} console.log(rangeIterator.next()); // {value: "1", done: false} console.log(rangeIterator.next()); // {value: "2", done: false} ... console.log(rangeIterator.next()); // {value: "9", done: false} console.log(rangeIterator.next()); // {done: true} 

يعمل هذا المثال مع سلسلة ، نظرًا لأن String.prototype له مكرر ( spec ) خاص به . قائمة الأنواع القابلة للتكرار في js: String، Array، TypedArray، Map، Set.
بالإضافة إلى الحلقة ، يستخدم javascript Symbol.iterator في الإنشاءات التالية: معامل الانتشار ، العائد ، مهمة التدمير .


يؤدي استدعاء [Symbol.iterator] () إلى إرجاع واجهة مكررة تبدو كما يلي:


 Iterator { next(); //    return(); //   throw(); //   } 

تعد طرق .next () و .return () و. throw () (ثم ​​سنرى كيف) وإرجاع كائن من النموذج:


 { value - ,   done -    } 

يتم استخدام أساليب .return () و. throw () ، على سبيل المثال ، عندما ينتهي التكرار قبل الأوان. يمكنك قراءة المزيد عنها في مواصفات ecmascript .


باستخدام Symbol.iterator في بنيتها


على سبيل المثال ، لنقم بإنشاء هيكل خاص بنا ، والذي يمكن تكراره باستخدام لـ ... من وننظر أيضًا في استخدام Symbol.iterator مع بنيات اللغة أعلاه.


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


إنشاء فئة الطريق :


 class Route { stations; //      constructor(stations) { this.stations = stations; } //     id get(idx) { return this.stations[idx]; } //   [Symbol.iterator]() { return new RouteIterator(this); //   } } 

كما ترون ، فإن طريقنا يطبق طريقة Symbol.iterator ، وبالتالي فإن Route هو كيان ( المواصفات ) قابل للتكرار ، مما يعني أنه يمكننا المرور عبره باستخدام ... لـ (بعد أن ننظر إلى تطبيق RouteIterator ).


سيتم استدعاء الأسلوب [Symbol.iterator] () عدة مرات كما كانت هناك مكالمات إليها. أي إذا حاولت عدة دورات السير على الطريق الواحدة تلو الأخرى ، فسيتم استدعاء [Symbol.iterator] () لكل دورة ، لذلك لكل مكالمة نقوم بإنشاء مثيل جديد من RouteIterator .


الآن دعونا نتعرف على RouteIterator نفسها. تطبق هذه الفئة واجهة مكررة لكيان المسار . دعونا ننظر في الأمر:


 class RouteIterator { _route; //     _nextIdx; //    constructor(route) { this._route = route; this._nextIdx = 0; } next() { if (this._nextIdx === this._route.stations.length) { return { done: true } //     } const result = { value: this._route.get(this._nextIdx), done: false } this._nextIdx++; return result; } } 

في هذه الفئة ، لدينا إمكانية الوصول إلى المجموعة القابلة للتكرار (خاصية المسار ) ، وأيضًا nextIdx هو مؤشر إلى القيمة التالية في مجموعتنا.


تقوم الطريقة التالية () أولاً وقبل كل شيء بالتحقق مما إذا كان المسار قد اكتمل ، وإذا تم إكماله ، فتُرجع أن التكرارات كاملة. وإلا ، فإننا نأخذ القيمة التالية في مجموعة المسار ، ونقول إن التكرار لم يكتمل ، وانقل المؤشر وأرجع النتيجة.


الآن يمكننا المرور عبر مجموعة المسار من خلال ... لـ :


 const route = new Route(['', '', '']) for (let item of route) { console.log(item); } 

سوف يسرد هذا الرمز المحطات التي مررنا بها إلى Route .


الآن سنذهب عبر المحطات باستخدام مولدات الوظائف:


 function* gen() { yield* route; return 'x'; //        .next() } const g = gen(); g.next() // {value: "", done: false} g.next() // {value: "", done: false} g.next() // {value: "", done: false} g.next() // {value: 'x', done: true} g.next() // {value: undefined, done: true} 

يستخدم Symbol.iterator لإعادة الهيكلة :


 const [a, b, c] = route; // a - "" // b - "" //  - "" 

ومع عامل انتشار :


 function test(a, b, c) { console.log(a, b, c) } test(…route) // "" "" "" 

النتائج


أنشأنا صفنا ، وجعلناها قابلة للتكرار وتستخدم مع بنيات جافا سكريبت. شكرا لك على اهتمامك =).


المواد


من المستحيل إتقان المادة الجديدة بشكل كامل في مقالة واحدة فقط ، لذلك إليك بعض المقالات الإضافية:
حول نمط التكرار من كتاب إعادة بيع المعلم
حول رمز من كتاب ايليا كانتور وعلى MDN

Source: https://habr.com/ru/post/ar481548/


All Articles