Array.prototype.forEach()‎

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث

الدالة Array.prototype.forEach()‎ تستدعي دالةً لكل عنصر موجود في المصفوفة.

const arr = ['a', 'b', 'c'];

arr.forEach(function(element) {
    console.log(element);
});

// a
// b
// c

البنية العامة

arr.forEach(callback[, thisArg])

callback

الدالة التي ستُنفَّذ كل عنصر من عناصر المصفوفة، وتقبل ثلاثة وسائط.

currentValue

العنصر الحالي الذي يُعالِج في المصفوفة، وهذه القيمة مطلوبة.

index

فهرس العنصر الحالي في المصفوفة، وهذه القيمة اختيارية.

array

المصفوفة التي استدعيت الدالة forEach عليها، وهذه القيمة اختيارية.

thisArg

القيمة التي ستُستخدَم في this عند استدعاء الدالة callback، وهي قيمة اختيارية.

القيمة المعادة

undefined.

الوصف

الدالة forEach تُنفِّذ الدالة callback على كل عنصر موجود في المصفوفة. لاحظ أنَّ الدالة callback ستُستدعى على الفهارس التي لها قيمٌ مسندةٌ إليها، فهي لن تستدعى للفهارس التي حُذِفَت أو التي لم تُسنَد إليها قيم.

ستستدعى الدالة callback مع تمرير ثلاثة وسائط إليها: قيمة العنصر، وفهرسه، وكائن المصفوفة.

إذا وفّرنا المعامل thisArg إلى الدالة forEach، فسيستخدم كقيمة this داخل الدالة callback، وإن لم نُحدِّد له قيمةً فستستعمل القيمة undefined.

لاحظ أنَّ الدالة forEach لا تغيّر المصفوفة التي تستدعى عليها بأيّ شكلٍ من الأشكال.

من غير ممكن إيقاف حلقة تكرار forEach()‎ إلا برمي استثناء، وإن كنت تحتاج إلى إيقاف حلقة التكرار فلا يُنصَح باستخدام الدالة forEach()‎، وإنما استخدم حلقات التكرار العادية. إذا أردتَ اختبار قيم المصفوفة فاستخدم الدالة every()‎ أو some()‎، ويمكن استخدام الدوال الجديدة find()‎ و findIndex()‎ لمعرفة وجود قيمة ما.

أمثلة

استخدام forEach بدلًا من for

استخدام الحلقة for للمرور على عناصر المصفوفة:

const items = ['item1', 'item2', 'item3'];
const copy = [];

for (let i=0; i<items.length; i++) {
  copy.push(items[i])
}

استخدام الدالة forEach:

const items = ['item1', 'item2', 'item3'];
const copy = [];

items.forEach(function(item){
  copy.push(item)
});

طباعة محتوى مصفوفة

الشيفرة الآتية تطبع كل عنصر في المصفوفة في سطر:

function logArrayElements(element, index, array) {
  console.log('a[' + index + '] = ' + element);
}

// لاحظ أنَّ الفهرس 2 لم يُطبَع لعدم وجود عنصر في المصفوفة في هذا الفهرس
[2, 5, , 9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[3] = 9

استخدام الوسيط thisArg

المثال الآتي يُحدِّث خاصيات الكائن من كل عنصر من عناصر المصفوفة:

function Counter() {
  this.sum = 0;
  this.count = 0;
}
Counter.prototype.add = function(array) {
  array.forEach(function(entry) {
    this.sum += entry;
    ++this.count;
  }, this);
  // ^---- لاحظ هنا
};

const obj = new Counter();
obj.add([2, 5, 9]);
obj.count;
// 3 
obj.sum;
// 16

تعديل المصفوفة أثناء التكرار

المثال الآتي يعرض "one" و "two" و "four"، وعند الوصول إلى العنصر "two" فسيحذَف أوّل عنصر من المصفوفة (باستخدام الدالة shift)، مما يؤدي إلى تغيير مواضع العناصر البقية (أي أنها ستنتقل إلى الفهرس الذي يسبق موضعها الحالي). ولأنَّ العنصر "four" أصبح في الفهرس الذي يسبقه فسيتم تجاوز العنصر "three"؛ لاحظ أنَّ الدالة forEach لا تنسخ المصفوفة قبل بدء الدوران على عناصرها:

var words = ['one', 'two', 'three', 'four'];
words.forEach(function(word) {
  console.log(word);
  if (word === 'two') {
    words.shift();
  }
});
// one
// two
// four

تعويض نقص دعم المتصفحات

أضيفت هذه الدالة في الإصدار الخامس من معيار ECMAScript، لذا يمكنك استخدام الشيفرة الآتية لإضافتها للمتصفحات التي لا تدعمها:

// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
if (!Array.prototype.forEach) {

  Array.prototype.forEach = function(callback/*, thisArg*/) {

    var T, k;

    if (this == null) {
      throw new TypeError('this is null or not defined');
    }

    // 1. Let O be the result of calling toObject() passing the
    // |this| value as the argument.
    var O = Object(this);

    // 2. Let lenValue be the result of calling the Get() internal
    // method of O with the argument "length".
    // 3. Let len be toUint32(lenValue).
    var len = O.length >>> 0;

    // 4. If isCallable(callback) is false, throw a TypeError exception. 
    // See: http://es5.github.com/#x9.11
    if (typeof callback !== 'function') {
      throw new TypeError(callback + ' is not a function');
    }

    // 5. If thisArg was supplied, let T be thisArg; else let
    // T be undefined.
    if (arguments.length > 1) {
      T = arguments[1];
    }

    // 6. Let k be 0.
    k = 0;

    // 7. Repeat while k < len.
    while (k < len) {

      var kValue;

      // a. Let Pk be ToString(k).
      //    This is implicit for LHS operands of the in operator.
      // b. Let kPresent be the result of calling the HasProperty
      //    internal method of O with argument Pk.
      //    This step can be combined with c.
      // c. If kPresent is true, then
      if (k in O) {

        // i. Let kValue be the result of calling the Get internal
        // method of O with argument Pk.
        kValue = O[k];

        // ii. Call the Call internal method of callback with T as
        // the this value and argument list containing kValue, k, and O.
        callback.call(T, kValue, k, O);
      }
      // d. Increase k by 1.
      k++;
    }
    // 8. return undefined.
  };
}

دعم المتصفحات

الميزة Chrome Firefox Internet Explorer Opera Safari
الدعم الأساسي نعم نعم 9 نعم نعم

مصادر ومواصفات