for...of
في JavaScript
التعبير البرمجي for...of
يمر على الكائنات التي يمكن الدوران على عناصرها (iterable objects) بما في ذلك الكائن Array
و Map
و Set
و String
و TypedArray
و Arguments
، وتنفيذ تعابير برمجية معيّنة على قيمة كل خاصية من خاصيات تلك الكائنات.
البنية العامة
for (variable of iterable) {
statement
}
variable
ستُنسَد قيمة الخاصية مختلفة لهذا المتغير في كل دورة.
iterable
خاصيات الكائن القابلة للدوران (iterable properties).
الوصف
الفرق بين حلقتَي التكرار for...of
و for...in
التعبيران البرمجيان for...in
و for...of
يُستخدَمان للدوران على شيءٍ ما، لكن الاختلاف الرئيسي بينهما هو ما هي الأشياء التي تدور حلقة التكرار عليها.
فالتعبير for...in
يدور على الخاصيات الكائن القابلة للإحصاء (enumerable properties) بترتيب إدخالها الأصلي.
أما التعبير for...of
فسيدور على البيانات التي يُعرِّفها كائن iterable
على أنها قابلة للدوران.
for...of
و for...in
عند استخدامهما على كائن Array
:Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
let iterable = [3, 5, 7];
iterable.foo = 'hello';
for (let i in iterable) {
console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom"
}
for (let i in iterable) {
if (iterable.hasOwnProperty(i)) {
console.log(i); // 0, 1, 2, "foo"
}
}
for (let i of iterable) {
console.log(i); // 3, 5, 7
}
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
let iterable = [3, 5, 7];
iterable.foo = 'hello';
objCustom
وكل كائن Array
سيرث الخاصية arrCustom
وذلك بسبب إضافة تلك الخاصيات إلى Object.prototype
و Array.prototype
؛ وبالتالي سيرثها الكائن iterable
.for (let i in iterable) {
console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom"
}
3
أو 5
أو 7
أو hello
لأنها لا تُعدّ خاصياتٍ قابلةً للإحصاء؛ لكنها ستعرض فهارس المصفوفة والخاصية arrCustom
و objCustom
، لمزيدٍ من المعلومات راجع صفحة for...in
.for (let i in iterable) {
if (iterable.hasOwnProperty(i)) {
console.log(i); // 0, 1, 2, "foo"
}
}
hasOwnProperty()
للتأكد إذا كانت الخاصية تابعةً للكائن مباشرةً وليست خاصيةً موروثةً؛ لذا ستُعرَض الخاصيات 0
و 1
و 2
و foo
لأنها تابعة مباشرةً للكائن، ولن تُعرَض الخاصيات arrCustom
و objCustom
لأنها موروثة.for (let i of iterable) {
console.log(i); // 3, 5, 7
}
iterable
أنه يمكن المرور عليها، وهي عناصر المصفوفة 3
و 5
و 7
ولن تُعرَض خاصيات الكائن قط.
إنهاء التكرارات
يمكن إنهاء عملية الدوران في حلقاتfor...of
باستخدام التعابير البرمجية break
أو continue
أو throw
أو return
:function* foo(){
yield 1;
yield 2;
yield 3;
};
for (let o of foo()) {
console.log(o);
break; // إغلاق التكرار
}
أمثلة
المرور على Array
let iterable = [10, 20, 30];
for (let value of iterable) {
value += 1;
console.log(value);
}
// 11
// 21
// 31
const
بدلًا من let
، لكن حينئذٍ لن تتمكن من إعادة إسناد قيمة للمتغير داخل الكتلة:let iterable = [10, 20, 30];
for (const value of iterable) {
console.log(value);
}
// 10
// 20
// 30
المرور على String
let iterable = 'boo';
for (let value of iterable) {
console.log(value);
}
// "b"
// "o"
// "o"
المرور على TypedArray
let iterable = new Uint8Array([0x00, 0xff]);
for (let value of iterable) {
console.log(value);
}
// 0
// 255
المرور على Map
let iterable = new Map([['a', 1], ['b', 2], ['c', 3]]);
for (let entry of iterable) {
console.log(entry);
}
// ['a', 1]
// ['b', 2]
// ['c', 3]
for (let [key, value] of iterable) {
console.log(value);
}
// 1
// 2
// 3
المرور على Set
let iterable = new Set([1, 1, 2, 2, 3, 3]);
for (let value of iterable) {
console.log(value);
}
// 1
// 2
// 3
المرور على كائن Arguments
(function() {
for (let argument of arguments) {
console.log(argument);
}
})(1, 2, 3);
// 1
// 2
// 3
المرور على قائمة عقد في DOM
يمكن المرور على قائمة عقد في DOM مثلNodeList
، فالمثال الآتي يُضيف الصنف read
إلى الفقرات <p>
التي تكون أبناءً مباشرين للعنصر <article>
:let articleParagraphs = document.querySelectorAll('article > p');
for (let paragraph of articleParagraphs) {
paragraph.classList.add('read');
}
المرور على المولِّدات
function* fibonacci() { // دالة مولِّدة
let [prev, curr] = [0, 1];
while (true) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (let n of fibonacci()) {
console.log(n);
// إيقاف السلسلة عند العدد 1000
if (n >= 1000) {
break;
}
}
المرور على الكائنات التي تُطبِّق بروتوكول iterable
يمكن أيضًا استخدام حلقة التكرارfor...of
للمرور على الكائنات التي تُطبِّق بروتوكول iterable صراحةً:var iterable = {
[Symbol.iterator]() {
return {
i: 0,
next() {
if (this.i < 3) {
return { value: this.i++, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (var value of iterable) {
console.log(value);
}
// 0
// 1
// 2
دعم المتصفحات
الميزة | Chrome | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
الدعم الأساسي | 38 | 13 | غير مدعومة | 25 | 8 |
إغلاق التكرارات | 51 | 53 | غير مدعومة | مدعومة | مدعومة |
مصادر ومواصفات
- مسودة المعيار ECMAScript Latest Draft.
- معيار ECMAScript 2015 (6th Edition).