حلقة من خلال مصفوفة في JavaScript

سئل على ١٠ يونيو ٢٠١٠  ·  تمت مشاهدة 3.9M مرة  ·  مصدر

Mark Szymanski picture
في ١٠ يونيو ٢٠١٠

في Java يمكنك استخدام حلقة for لاجتياز الكائنات في مصفوفة كما يلي:

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray)
{
    // Do something
}

هل يمكنك أن تفعل الشيء نفسه في JavaScript؟

الإجابات

Christian C. Salvadó picture
في ١٠ يونيو ٢٠١٠
4183

لديك عدة خيارات:

1. حلقة تسلسلية for :

var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    console.log(myStringArray[i]);
    //Do something
}

الايجابيات

  • يعمل في كل بيئة
  • يمكنك استخدام عبارات التحكم في التدفق break و continue

سلبيات

  • مطول جدا
  • صيغة الامر
  • من السهل أن يكون لديك أخطاء متقطعة (تسمى أحيانًا خطأ آخر في السياج )

2. Array.prototype.forEach

قدمت مواصفات Array.prototype.forEach ، أعطانا طريقة موجزة للتكرار عبر مصفوفة:

const array = ["one", "two", "three"]
array.forEach(function (item, index) {
  console.log(item, index);
});

بعد مرور ما يقرب من عشر سنوات على كتابة مواصفات ES5 (ديسمبر 2009) ، تم تنفيذها من قبل جميع المحركات الحديثة تقريبًا في بيئات سطح المكتب والخادم والجوّال ، لذا فهي آمنة للاستخدام.

ومع تركيب وظيفة السهم ES6 ، يصبح الأمر أكثر إيجازًا:

array.forEach(item => console.log(item));

يتم أيضًا تنفيذ وظائف الأسهم على نطاق واسع إلا إذا كنت تخطط لدعم الأنظمة الأساسية القديمة (على سبيل المثال ، Internet Explorer 11 ) ؛ أنت أيضا بأمان للذهاب.

الايجابيات

  • قصير جدا ومختصر.
  • تصريحي

سلبيات

  • لا يمكن استخدام break / continue

عادة ، يمكنك استبدال الحاجة إلى break من الحلقات الإلزامية عن طريق تصفية عناصر المصفوفة قبل تكرارها ، على سبيل المثال:

array.filter(item => item.condition < 10)
     .forEach(item => console.log(item))

ضع في اعتبارك إذا كنت تقوم بتكرار مصفوفة لإنشاء مصفوفة أخرى منه ، فيجب عليك استخدام map . لقد رأيت هذا النمط المضاد مرات عديدة.

مكافحة النمط:

const numbers = [1,2,3,4,5], doubled = [];

numbers.forEach((n, i) => { doubled[i] = n * 2 });

حالة الاستخدام السليم للخريطة :

const numbers = [1,2,3,4,5];
const doubled = numbers.map(n => n * 2);

console.log(doubled);

أيضا، إذا كنت تحاول الحد من مجموعة إلى قيمة، على سبيل المثال، كنت تريد جمع مجموعة من الأرقام، يجب عليك استخدام الحد الأسلوب.

مكافحة النمط:

const numbers = [1,2,3,4,5];
const sum = 0;
numbers.forEach(num => { sum += num });

الاستخدام السليم لتقليل :

const numbers = [1,2,3,4,5];
const sum = numbers.reduce((total, n) => total + n, 0);

console.log(sum);

3. ES6 for-of كشف حساب

يقدم معيار ES6 مفهوم الكائنات القابلة للتكرار ويحدد بنية جديدة لعبور البيانات ، وهي عبارة for...of .

تعمل هذه العبارة مع أي نوع من الكائنات القابلة للتكرار وأيضًا للمولدات (أي كائن له خاصية \[Symbol.iterator\] ).

كائنات المصفوفة هي بحكم تعريفها متكررات مضمنة في ES6 ، لذا يمكنك استخدام هذه العبارة عليها:

let colors = ['red', 'green', 'blue'];
for (const color of colors){
    console.log(color);
}

الايجابيات

  • يمكنه التكرار على مجموعة كبيرة ومتنوعة من الكائنات.
  • يمكن استخدام عبارات التحكم في التدفق العادي ( break / continue ).
  • مفيد لتكرار القيم غير المتزامنة بشكل تسلسلي.

سلبيات

  • إذا كنت تستهدف المتصفحات القديمة، وإخراج transpiled قد مفاجأة لك .

لا تستخدم for...in

يقترحzipcodeman استخدام العبارة for...in ، ولكن بالنسبة إلى المصفوفات المتكررة ، يجب تجنب for-in ، فإن هذه العبارة تهدف إلى تعداد خصائص الكائن.

لا يجب استخدامه مع كائنات تشبه المصفوفة للأسباب التالية:

  • ترتيب التكرار غير مضمون ؛ لا يجوز زيارة فهارس المصفوفة بترتيب رقمي.
  • يتم أيضًا تعداد الخصائص الموروثة.

النقطة الثانية هي أنه يمكن أن يعطيك الكثير من المشاكل ، على سبيل المثال ، إذا قمت بتوسيع العنصر Array.prototype لتضمين طريقة هناك ، فسيتم تعداد هذه الخاصية أيضًا.

فمثلا:

Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];

for (var i in array) {
    console.log(array[i]);
}

سوف يقوم الكود أعلاه بوحدة التحكم في السجل "a" و "b" و "c" و "foo!".

يمكن أن يكون ذلك مشكلة خاصة إذا كنت تستخدم بعض المكتبات التي تعتمد بشكل كبير على زيادة النماذج الأصلية (مثل MooTools ).

العبارة for-in ، كما قلت من قبل ، موجودة لتعداد خصائص الكائن ، على سبيل المثال:

var obj = {
    "a": 1,
    "b": 2,
    "c": 3
};

for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) {
        // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
        console.log("prop: " + prop + " value: " + obj[prop])
    }
}

في المثال أعلاه ، تتيح لك الطريقة hasOwnProperty تعداد الخصائص الخاصة فقط. هذا كل شيء ، فقط الخصائص التي يمتلكها الكائن ماديًا ، لا توجد خصائص موروثة.

أنصحك بقراءة المقال التالي:

Mark Reed picture
في ١٦ أبريل ٢٠١٢
1126

نعم ، بافتراض أن تطبيقك يتضمن ميزة for ... of المقدمة في ECMAScript 2015 (إصدار "Harmony") ... وهو افتراض آمن جدًا هذه الأيام.

يعمل مثل هذا:

// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
  // ... do something with s ...
}

أو الأفضل من ذلك ، نظرًا لأن ECMAScript 2015 يوفر أيضًا متغيرات ذات نطاق الكتلة:

// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
  // ... do something with s ...
}
// s is no longer defined here

(يختلف المتغير s في كل تكرار ، ولكن لا يزال من الممكن الإعلان عن const داخل جسم الحلقة طالما لم يتم تعديله هناك.)

ملاحظة حول المصفوفات المتفرقة: قد لا تخزن المصفوفة في JavaScript في الواقع العديد من العناصر كما تم الإبلاغ عنها بواسطة length ؛ أن الرقم المبلغ عنه هو ببساطة أكبر من أعلى مؤشر يتم تخزين القيمة عنده. إذا كانت المصفوفة تحتوي على عدد أقل من العناصر المشار إليها بطولها ، فيُقال أنها قليلة . على سبيل المثال ، من الشرعي تمامًا وجود مصفوفة تحتوي على عناصر فقط في الفهارس 3 و 12 و 247 ؛ تم الإبلاغ عن length لمصفوفة كهذه على أنها 248 ، على الرغم من أنها تخزن 3 قيم فقط. إذا حاولت الوصول إلى عنصر في أي فهرس آخر ، فسيظهر للمصفوفة قيمة undefined هناك. لذلك عندما تريد "تكرار" مصفوفة ، لديك سؤال للإجابة عليه: هل تريد تكرار النطاق الكامل المشار إليه بطولها ومعالجة undefined s بحثًا عن أي عناصر مفقودة ، أم هل تريد ذلك فقط تريد معالجة العناصر الموجودة بالفعل؟ هناك الكثير من التطبيقات لكلا النهجين ؛ يعتمد ذلك فقط على ما تستخدم المصفوفة من أجله.

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

بالطبع ، ليس لدى بعض المطورين خيار سوى استخدام نهج مختلف على أي حال ، لأنهم لأي سبب من الأسباب يستهدفون إصدارًا من JavaScript لا يدعم حتى الآن for ... of .

طالما أن تطبيق JavaScript الخاص بك متوافق مع الإصدار السابق من مواصفات ECMAScript (التي تستبعد ، على سبيل المثال ، إصدارات Internet Explorer قبل 9) ، يمكنك استخدام طريقة التكرار Array#forEach بدلاً من التكرار الحلقي. في هذه الحالة ، تقوم بتمرير دالة ليتم استدعاؤها على كل عنصر في المصفوفة:

var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) { 
     // ... do something with s ...
} );

بخلاف for ... of ، يستدعي .forEach وظيفة العناصر الموجودة بالفعل في المصفوفة فقط. إذا مررنا المصفوفة الافتراضية المكونة من ثلاثة عناصر وطولها 248 ، فسوف تستدعي الدالة ثلاث مرات فقط ، وليس 248 مرة. كما أنه يميز بين العناصر المفقودة والعناصر التي تم تعيينها بالفعل على undefined ؛ بالنسبة للأخير ، سيستمر استدعاء الوظيفة ، ويمرر undefined كوسيطة. إذا كانت هذه هي الطريقة التي تريد بها التعامل مع المصفوفات المتناثرة ، فقد يكون .forEach هو السبيل للذهاب حتى إذا كان المترجم الخاص بك يدعم for ... of .

الخيار الأخير ، الذي يعمل في جميع إصدارات JavaScript ، عبارة عن حلقة عد صريحة . يمكنك ببساطة العد من 0 إلى واحد أقل من الطول واستخدام العداد كمؤشر. تبدو الحلقة الأساسية كما يلي:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  s = myStringArray[i];
  // ... do something with s ...
}

تتمثل إحدى ميزات هذا الأسلوب في أنه يمكنك اختيار كيفية التعامل مع المصفوفات المتناثرة ؛ ستعمل الشفرة أعلاه على تشغيل جسم الحلقة بالكامل length مرة ، مع ضبط s على undefined لأي عناصر مفقودة ، تمامًا مثل for .. of . إذا كنت تريد بدلاً من ذلك التعامل مع العناصر الموجودة فعليًا فقط لمصفوفة متفرقة ، مثل .forEach ، فيمكنك إضافة اختبار بسيط in على الفهرس:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  if (i in myStringArray) {
    s = myStringArray[i];
    // ... do something with s ...
  }
}

يمكن أن يؤدي تعيين قيمة الطول إلى المتغير المحلي (بدلاً من تضمين التعبير الكامل myStringArray.length في حالة الحلقة) إلى إحداث فرق كبير في الأداء نظرًا لأنه يتخطى البحث عن الخاصية في كل مرة ؛ باستخدام Rhino على جهازي ، فإن التسريع هو 43٪.

قد ترى أن طول التخزين المؤقت تم في بند تهيئة الحلقة ، مثل هذا:

var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {

تعني حلقة العد الصريح أيضًا أن لديك حق الوصول إلى فهرس كل قيمة ، إذا كنت تريد ذلك. يتم أيضًا تمرير الفهرس كمعامل إضافي للدالة التي تمررها إلى forEach ، لذا يمكنك الوصول إليه بهذه الطريقة أيضًا:

myStringArray.forEach( function(s, i) {
   // ... do something with s and i ...
});

for ... of لا يمنحك الفهرس المرتبط بكل كائن ، ولكن طالما أن الكائن الذي تكرره هو في الواقع Array ( for .. of يعمل مع أنواع أخرى قابلة للتكرار والتي قد لا تحتوي على هذه الطريقة) ، يمكنك استخدام طريقة Array # إدخالات لتغييرها إلى مجموعة من أزواج [index، item] ، ثم التكرار فوق ذلك:

for (const [i, s] of myStringArray.entries()) {
  // ... do something with s and i ...
}

الصيغة for ... in التي ذكرها الآخرون هي للتكرار على خصائص الكائن ؛ نظرًا لأن المصفوفة في JavaScript هي مجرد كائن له أسماء خصائص رقمية (وخاصية length تم تحديثها تلقائيًا) ، يمكنك نظريًا إجراء حلقة حول مصفوفة بها. لكن المشكلة هي أنها لا تقيد نفسها بقيم الخصائص الرقمية (تذكر أن حتى الطرق هي في الواقع مجرد خصائص تكون قيمتها إغلاقًا) ، كما أنها غير مضمونة للتكرار على تلك الموجودة في الترتيب الرقمي. لذلك ، لا يجب استخدام بناء الجملة for ... in للتكرار عبر المصفوفات.

hasen picture
في ١٠ يونيو ٢٠١٠
447

يمكنك استخدام map ، وهي تقنية برمجة وظيفية متوفرة أيضًا بلغات أخرى مثل Python و Haskell .

[1,2,3,4].map( function(item) {
     alert(item);
})

الصيغة العامة هي:

array.map(func)

بشكل عام ، سيأخذ func معلمة واحدة ، وهي عنصر من المصفوفة. ولكن في حالة JavaScript ، يمكن أن يستغرق الأمر معاملًا ثانيًا وهو فهرس العنصر ، ومعامل ثالث وهو المصفوفة نفسها.

قيمة الإرجاع array.map هي مصفوفة أخرى ، لذا يمكنك استخدامها على النحو التالي:

var x = [1,2,3,4].map( function(item) {return item * 10;});

والآن x تساوي [10,20,30,40] .

ليس عليك كتابة الوظيفة في السطر. يمكن أن تكون وظيفة منفصلة.

var item_processor = function(item) {
      // Do something complicated to an item
}

new_list = my_list.map(item_processor);

والذي سيكون نوعًا مكافئًا لـ:

 for (item in my_list) {item_processor(item);}

إلا أنك لا تحصل على new_list .

Marlon Bernardes picture
في ١١ أغسطس ٢٠١٣
131

لـ (const s of myStringArray) {

(الإجابة مباشرة على سؤالك: الآن يمكنك ذلك!)

معظم الإجابات الأخرى صحيحة ، لكنها لم تذكر (حتى كتابة هذه السطور) أن ECMAScript 6 2015 تقدم آلية جديدة لإجراء التكرار ، الحلقة for..of .

هذه الصيغة الجديدة هي الطريقة الأكثر أناقة لتكرار مصفوفة في JavaScript (طالما أنك لا تحتاج إلى فهرس التكرار).

يعمل حاليًا مع Firefox 13+ و Chrome 37+ ولا يعمل أصلاً مع المتصفحات الأخرى (انظر توافق المتصفح أدناه). لحسن الحظ ، لدينا برامج تجميع JavaScript (مثل Babel ) تتيح لنا استخدام ميزات الجيل التالي اليوم.

كما أنه يعمل على Node.js (قمت باختباره في الإصدار 0.12.0).

تكرار مصفوفة

// You could also use "let" or "const" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) {
   console.log(letter);
}

تكرار مجموعة من الكائنات

const band = [
  {firstName : 'John', lastName: 'Lennon'},
  {firstName : 'Paul', lastName: 'McCartney'}
];

for(const member of band){
  console.log(member.firstName + ' ' + member.lastName);
}

تكرار المولد:

(مثال مستخرج من https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of )

function* fibonacci() { // A generator function
  let [prev, curr] = [1, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (const n of fibonacci()) {
  console.log(n);
  // Truncate the sequence at 1000
  if (n >= 1000) {
    break;
  }
}

جدول التوافق: http://kangax.github.io/es5-compat-table/es6/#For..of الحلقات

المواصفات: http://wiki.ecmascript.org/doku.php؟id=harmony:iterators

}

sebarmeli picture
في ٧ ديسمبر ٢٠١٠
123

في JavaScript ، لا يُنصح بالتكرار عبر مصفوفة مع حلقة for-in ، ولكن من الأفضل استخدام حلقة for مثل:

for(var i=0, len=myArray.length; i < len; i++){}

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

kennebec picture
في ١٠ يونيو ٢٠١٠
92

تشترك كل من Opera و Safari و Firefox و Chrome في مجموعة من أساليب المصفوفة المحسّنة لتحسين العديد من الحلقات الشائعة.

قد لا تحتاج إليها جميعًا ، لكنها يمكن أن تكون مفيدة جدًا ، أو ستكون كذلك إذا كان كل متصفح يدعمها.

قامت Mozilla Labs بنشر الخوارزميات التي يستخدمها كلاهما و WebKit ، بحيث يمكنك إضافتها بنفسك.

يقوم عامل التصفية بإرجاع مصفوفة من العناصر التي تحقق شرطًا أو اختبارًا.

كل إرجاع صحيح إذا اجتاز كل عضو مصفوفة الاختبار.

يعود البعض صحيحًا إذا نجح أي منهم في الاختبار.

forEach يدير دالة على كل عضو في مصفوفة ولا يعيد أي شيء.

خريطة مثل forEach، ولكن تقوم بإرجاع مجموعة من نتائج العملية لكل عنصر.

تأخذ كل هذه التوابع دالة في الوسيطة الأولى ولديها وسيطة ثانية اختيارية ، وهي كائن تريد أن تفرض نطاقه على أعضاء المصفوفة أثناء تكرارها خلال الوظيفة.

تجاهلها حتى تحتاجها.

indexOf و lastIndexOf ابحث عن الموضع المناسب للعنصر الأول أو الأخير الذي يطابق

(function(){
    var p, ap= Array.prototype, p2={
        filter: function(fun, scope){
            var L= this.length, A= [], i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        val= this[i];
                        if(fun.call(scope, val, i, this)){
                            A[A.length]= val;
                        }
                    }
                    ++i;
                }
            }
            return A;
        },
        every: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && !fun.call(scope, this[i], i, this))
                        return false;
                    ++i;
                }
                return true;
            }
            return null;
        },
        forEach: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
            }
            return this;
        },
        indexOf: function(what, i){
            i= i || 0;
            var L= this.length;
            while(i< L){
                if(this[i]=== what)
                    return i;
                ++i;
            }
            return -1;
        },
        lastIndexOf: function(what, i){
            var L= this.length;
            i= i || L-1;
            if(isNaN(i) || i>= L)
                i= L-1;
            else
                if(i< 0) i += L;
            while(i> -1){
                if(this[i]=== what)
                    return i;
                --i;
            }
            return -1;
        },
        map: function(fun, scope){
            var L= this.length, A= Array(this.length), i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        A[i]= fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
                return A;
            }
        },
        some: function(fun, scope){
            var i= 0, L= this.length;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && fun.call(scope, this[i], i, this))
                        return true;
                    ++i;
                }
                return false;
            }
        }
    }
    for(p in p2){
        if(!ap[p])
            ap[p]= p2[p];
    }
    return true;
})();
John Slegers picture
في ٢٩ فبراير ٢٠١٦
78

المقدمة

منذ أن كنت في الكلية ، قمت ببرمجة Java و JavaScript و Pascal و ABAP و PHP و Progress 4GL و C / C ++ وربما بعض اللغات الأخرى التي لا يمكنني التفكير فيها الآن.

في حين أن جميعهم لديهم خصائصهم اللغوية الخاصة ، فإن كل لغة من هذه اللغات تشترك في العديد من نفس المفاهيم الأساسية. تتضمن هذه المفاهيم الإجراءات / الوظائف و IF -statements و FOR -loops و WHILE -loops.


حلقة تقليدية for

تتكون الحلقة التقليدية for ثلاثة مكونات:

  1. التهيئة: يتم تنفيذها قبل تنفيذ كتلة البحث في المرة الأولى
  2. الشرط: يتحقق من الشرط في كل مرة قبل تنفيذ كتلة الحلقة ، ويخرج الحلقة إذا كان خطأ
  3. الفكرة اللاحقة: يتم إجراؤها في كل مرة بعد تنفيذ كتلة الحلقة

يتم فصل هذه المكونات الثلاثة عن بعضها البعض بواسطة رمز ; . يعد محتوى كل مكون من هذه المكونات الثلاثة اختياريًا ، مما يعني أن ما يلي هو أقل حلقة ممكنة من for :

for (;;) {
    // Do stuff
}

بالطبع ، ستحتاج إلى تضمين if(condition === true) { break; } أو if(condition === true) { return; } مكان ما داخل حلقة for لإيقاف تشغيلها.

عادة ، على الرغم من ذلك ، يتم استخدام التهيئة للإعلان عن فهرس ، ويتم استخدام الشرط لمقارنة هذا الفهرس بحد أدنى أو أقصى قيمة ، ويتم استخدام الفكرة اللاحقة لزيادة الفهرس:

for (var i = 0, length = 10; i < length; i++) {
    console.log(i);
}

استخدام حلقة تقليدية for للتكرار خلال مصفوفة

الطريقة التقليدية للتكرار خلال المصفوفة هي:

for (var i = 0, length = myArray.length; i < length; i++) {
    console.log(myArray[i]);
}

أو ، إذا كنت تفضل التكرار العكسي ، فقم بما يلي:

for (var i = myArray.length - 1; i > -1; i--) {
    console.log(myArray[i]);
}

ومع ذلك ، هناك العديد من الاختلافات الممكنة ، مثل هذا على سبيل المثال:

for (var key = 0, value = myArray[key], length = myArray.length; key < length; value = myArray[++key]) {
    console.log(value);
}

...ما سر جديدة هذا...

var i = 0, length = myArray.length;
for (; i < length;) {
    console.log(myArray[i]);
    i++;
}

...ما سر جديدة هذا:

var key = 0, value;
for (; value = myArray[key++];){
    console.log(value);
}

أيهما يعمل بشكل أفضل هو إلى حد كبير مسألة الذوق الشخصي وحالة الاستخدام المحددة التي تنفذها.

لاحظ أن كل هذه الأشكال مدعومة من قبل جميع المتصفحات ، بما في ذلك المتصفحات القديمة جدًا!


حلقة A while

أحد البدائل لحلقة for هو حلقة while . للتكرار خلال مصفوفة ، يمكنك القيام بذلك:

var key = 0;
while(value = myArray[key++]){
    console.log(value);
}

مثل الحلقات التقليدية for ، فإن الحلقات while مدعومة من قبل أقدم المتصفحات.

لاحظ أيضًا أنه يمكن إعادة كتابة كل حلقة أثناء حلقة for . على سبيل المثال ، تتصرف حلقة while هنا بنفس الطريقة تمامًا مثل حلقة for هذه:

for(var key = 0; value = myArray[key++];){
    console.log(value);
}

For...in و for...of

في JavaScript ، يمكنك أيضًا القيام بما يلي:

for (i in myArray) {
    console.log(myArray[i]);
}

ومع ذلك ، يجب استخدام هذا بحذر ، حيث إنه لا يتصرف مثل الحلقة التقليدية for في جميع الحالات ، وهناك آثار جانبية محتملة يجب أخذها في الاعتبار. راجع لماذا يعتبر استخدام "for ... in" لتكرار المصفوفة فكرة سيئة؟ لمزيد من التفاصيل.

كبديل لـ for...in ، يوجد الآن أيضًا for...of . يوضح المثال التالي الفرق بين حلقة for...of وحلقة for...in :

var myArray = [3, 5, 7];
myArray.foo = "hello";

for (var i in myArray) {
  console.log(i); // logs 0, 1, 2, "foo"
}

for (var i of myArray) {
  console.log(i); // logs 3, 5, 7
}

بالإضافة إلى ذلك ، يجب أن تأخذ في الاعتبار أنه لا يوجد إصدار من Internet Explorer يدعم for...of ( Edge 12+ يفعل ذلك) وأن for...in يتطلب Internet Explorer 10 على الأقل.


Array.prototype.forEach()

البديل لـ for -loops هو Array.prototype.forEach() ، والذي يستخدم الصيغة التالية:

myArray.forEach(function(value, key, myArray) {
    console.log(value);
});

Array.prototype.forEach() بواسطة جميع المتصفحات الحديثة ، بالإضافة إلى Internet Explorer 9 والإصدارات الأحدث.


مكتبات

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

jQuery.each() في jQuery :

$.each(myArray, function(key, value) {
    console.log(value);
});

_.each() ، بالشرطة السفلية :

_.each(myArray, function(value, key, myArray) {
    console.log(value);
});

_.forEach() في لداش :

_.forEach(myArray, function(value, key) {
    console.log(value);
});
Timo Huovinen picture
في ٥ يناير ٢٠١٢
69

استخدم حلقة while ...

var i = 0, item, items = ['one', 'two', 'three'];
while(item = items[i++]){
    console.log(item);
}

يسجل: "واحد" و "اثنان" و "ثلاثة"

وللترتيب العكسي ، حلقة أكثر فاعلية:

var items = ['one', 'two', 'three'], i = items.length;
while(i--){
    console.log(items[i]);
}

يسجل: "ثلاثة" و "اثنان" و "واحد"

أو الحلقة الكلاسيكية for :

var items = ['one', 'two', 'three']
for(var i=0, l = items.length; i < l; i++){
    console.log(items[i]);
}

يسجل: "واحد" ، "اثنان" ، "ثلاثة"

المرجع: إغلاق Google: كيف لا تكتب JavaScript

Phrogz picture
في ٤ يونيو ٢٠١٢
40

إذا كنت تريد طريقة مقتضب لكتابة حلقة سريعة ويمكنك تكرار في الاتجاه المعاكس:

for (var i=myArray.length;i--;){
  var item=myArray[i];
}

هذا له فائدة تخزين الطول (على غرار for (var i=0, len=myArray.length; i<len; ++i) وعلى عكس for (var i=0; i<myArray.length; ++i) ) مع تقليل عدد الأحرف للكتابة.

هناك أيضًا بعض الأوقات التي يجب عليك فيها التكرار العكسي ، مثل عند التكرار عبر NodeList الحية حيث تخطط لإزالة العناصر من DOM أثناء التكرار.

Yuci picture
في ٢٣ فبراير ٢٠١٨
38

يستخدم البعض حالات التكرار عبر مصفوفة بطريقة البرمجة الوظيفية في JavaScript:

1. مجرد حلقة من خلال مجموعة

const myArray = [{x:100}, {x:200}, {x:300}];

myArray.forEach((element, index, array) => {
    console.log(element.x); // 100, 200, 300
    console.log(index); // 0, 1, 2
    console.log(array); // same myArray object 3 times
});

ملاحظة: Array.prototype.forEach () ليست طريقة وظيفية بالمعنى الدقيق للكلمة ، لأن الوظيفة التي تأخذها كمعامل إدخال ليس من المفترض أن تعيد قيمة ، وبالتالي لا يمكن اعتبارها وظيفة خالصة.

2. تحقق مما إذا كان أي من العناصر في المصفوفة يجتاز الاختبار

const people = [
    {name: 'John', age: 23}, 
    {name: 'Andrew', age: 3}, 
    {name: 'Peter', age: 8}, 
    {name: 'Hanna', age: 14}, 
    {name: 'Adam', age: 37}];

const anyAdult = people.some(person => person.age >= 18);
console.log(anyAdult); // true

3. التحول إلى مجموعة جديدة

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => element.x);
console.log(newArray); // [100, 200, 300]

ملاحظة: تُنشئ طريقة map () مصفوفة جديدة بنتائج استدعاء دالة متوفرة على كل عنصر في المصفوفة المستدعاة.

4. جمع خاصية معينة ، وحساب متوسطها

const myArray = [{x:100}, {x:200}, {x:300}];

const sum = myArray.map(element => element.x).reduce((a, b) => a + b, 0);
console.log(sum); // 600 = 0 + 100 + 200 + 300

const average = sum / myArray.length;
console.log(average); // 200

5. إنشاء مصفوفة جديدة على أساس الأصل ولكن دون تعديلها

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => {
    return {
        ...element,
        x: element.x * 2
    };
});

console.log(myArray); // [100, 200, 300]
console.log(newArray); // [200, 400, 600]

6. عد عدد كل فئة

const people = [
    {name: 'John', group: 'A'}, 
    {name: 'Andrew', group: 'C'}, 
    {name: 'Peter', group: 'A'}, 
    {name: 'James', group: 'B'}, 
    {name: 'Hanna', group: 'A'}, 
    {name: 'Adam', group: 'B'}];

const groupInfo = people.reduce((groups, person) => {
    const {A = 0, B = 0, C = 0} = groups;
    if (person.group === 'A') {
        return {...groups, A: A + 1};
    } else if (person.group === 'B') {
        return {...groups, B: B + 1};
    } else {
        return {...groups, C: C + 1};
    }
}, {});

console.log(groupInfo); // {A: 3, C: 1, B: 2}

7. استرجع مجموعة فرعية من مصفوفة بناءً على معايير معينة

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray = myArray.filter(element => element.x > 250);
console.log(newArray); // [{x:300}] 

ملاحظة: تُنشئ طريقة filter () مصفوفة جديدة تحتوي على جميع العناصر التي تجتاز الاختبار الذي تم تنفيذه بواسطة الوظيفة المتوفرة.

8. فرز مجموعة

const people = [
  { name: "John", age: 21 },
  { name: "Peter", age: 31 },
  { name: "Andrew", age: 29 },
  { name: "Thomas", age: 25 }
];

let sortByAge = people.sort(function (p1, p2) {
  return p1.age - p2.age;
});

console.log(sortByAge);

enter image description here

9. ابحث عن عنصر في المصفوفة

const people = [ {name: "john", age:23},
                {name: "john", age:43},
                {name: "jim", age:101},
                {name: "bob", age:67} ];

const john = people.find(person => person.name === 'john');
console.log(john);

enter image description here

ترجع طريقة Array.prototype.find () قيمة العنصر الأول في المصفوفة التي تفي بوظيفة الاختبار المتوفرة.

المراجع