जावास्क्रिप्ट - लूप के लिए myArray.forEach बनाम की मात्रा


88

मैंने बहुत सारे प्रश्न देखे हैं जो प्रयोग करने का सुझाव देते हैं:

for (var i = 0; i < myArray.length; i++){ /* ... */ }

के बजाय:

for (var i in myArray){ /* ... */ }

सरणियों के लिए, असंगत पुनरावृत्ति के कारण ( यहां देखें )।


हालाँकि, मुझे ऐसा कुछ भी नहीं मिल रहा है जो ऑब्जेक्ट ओरिएंटेड लूप को पसंद करता हो:

myArray.forEach(function(item, index){ /* ... */ });

जो मुझे अधिक सहज लगता है।

मेरे वर्तमान प्रोजेक्ट के लिए, IE8 कंपैटिबिलिटी महत्वपूर्ण है, और मैं मोज़िला की पॉलीफ़िल का उपयोग करने पर विचार कर रहा हूं, हालांकि मुझे यकीन नहीं है कि यह कैसे काम करेगा।

  • लूप के लिए मानक (उपरोक्त पहला उदाहरण) और आधुनिक ब्राउज़रों द्वारा Array.prototype.forEach कार्यान्वयन के बीच कोई अंतर है?
  • क्या आधुनिक ब्राउज़र कार्यान्वयन और मोज़िला के कार्यान्वयन के बीच कोई अंतर है (ऊपर IE8 के संबंध में)?
  • प्रदर्शन एक मुद्दे के रूप में ज्यादा नहीं है, बस निरंतरता है जिसके साथ गुणों को पुनरावृत्त किया जाता है।

6
इससे breakबाहर होना संभव नहीं है forEach। लेकिन एक बड़ा फायदा यह है कि फंक्शन के साथ एक नया स्कोप बनाया जाता है। पॉलीफ़िल के साथ आपको कोई समस्या नहीं होनी चाहिए (कम से कम मैंने किसी का सामना नहीं किया है)।
होजेबेल

पुराने IE के साथ आपको जो समस्याएँ हो सकती हैं, वह स्वयं शिम नहीं है, लेकिन टूटी हुई व्यूह रचनाकार / शाब्दिक wrt holesजहाँ undefinedहोनी चाहिए और अन्य टूटी हुई विधियाँ, जैसे sliceऔर hasOwnPropertyDOM प्रकार की DOM ऑब्जेक्ट्स के लिए wrt। मेरे परीक्षण और es5 shimविनिर्देशन के अनुरूप ऐसे शिमेड तरीकों को दिखाया गया है (एमडीएन के शिम का परीक्षण नहीं किया गया है)।
Xotic750

1
और एक forलूप से बाहर निकलने के लिए wrt , जो कि someके लिए है।
Xotic750

1
"हालांकि, मुझे ऐसा कुछ भी नहीं मिल रहा है जो ऑब्जेक्ट ओरिएंटेड लूप को पसंद करने के लिए लगता है:" मैं इसे कार्यात्मक तरीके बनाम अनिवार्य कहूंगा।
मेम्के

आप Array.find()पहले मैच को खोजने के बाद लूप से बाहर निकलने के लिए उपयोग कर सकते हैं ।
मत्ती

जवाबों:


121

forलूप और forEachविधि के बीच सबसे महत्वपूर्ण अंतर यह है कि, पूर्व के साथ, आप breakलूप से बाहर हो सकते हैं। आप continueकेवल पास किए गए फ़ंक्शन से लौटकर अनुकरण कर सकते हैं forEach, लेकिन पूरी तरह से बंद करने का कोई तरीका नहीं है।

इसके अलावा, दोनों प्रभावी रूप से एक ही कार्यक्षमता को पूरा करते हैं। एक अन्य मामूली अंतर में लूप के लिए सूचकांक (और सभी युक्त चर) का दायरा शामिल है, चर के कारण।

// 'i' is scoped to the containing function
for (var i = 0; i < arr.length; i++) { ... }

// 'i' is scoped to the internal function
arr.forEach(function (el, i) { ... });

हालाँकि, मुझे लगता है कि forEachयह बहुत अधिक अभिव्यंजक है - यह एक सरणी के प्रत्येक तत्व के माध्यम से पुनरावृति करने के आपके इरादे का प्रतिनिधित्व करता है, और यह आपको केवल सूचकांक नहीं, बल्कि तत्व का संदर्भ प्रदान करता है। कुल मिलाकर, यह ज्यादातर व्यक्तिगत स्वाद के लिए नीचे आता है, लेकिन यदि आप उपयोग कर सकते हैं forEach, तो मैं इसका उपयोग करने की सलाह दूंगा।


विशेष रूप से प्रदर्शन के बारे में, दोनों संस्करणों के बीच कुछ और पर्याप्त अंतर हैं। वास्तव में, लूप के लिए सरल forEachविधि की तुलना में काफी बेहतर प्रदर्शन करता है , जैसा कि इस जेस्पर टेस्ट द्वारा प्रदर्शित किया जाता है ।

यह तय करना आपके लिए आवश्यक है कि आपके लिए ऐसा प्रदर्शन आवश्यक है या नहीं, और ज्यादातर मामलों में, मैं गति पर अभिव्यक्तता का पक्ष लूंगा। इस गति का अंतर मूल लूप और विधि के बीच मामूली सिमेंटिक अंतर के कारण होने की संभावना है, जब विरल सरणियों पर काम करते हैं, जैसा कि इस उत्तर में दिया गया है ।

यदि आपको इसके व्यवहार की आवश्यकता नहीं है forEach और / या आपको लूप से जल्दी बाहर निकलने की आवश्यकता है, तो आप लो-डैश के _.eachविकल्प के रूप में उपयोग कर सकते हैं , जो क्रॉस-ब्राउज़र पर भी काम करेगा। यदि आप jQuery का उपयोग कर रहे हैं, तो यह एक समान भी प्रदान करता है $.each, बस प्रत्येक भिन्नता में कॉलबैक फ़ंक्शन को दिए गए तर्कों में अंतर पर ध्यान दें।

( forEachपॉलीफ़िल के रूप में, यह समस्याओं के बिना पुराने ब्राउज़रों में काम करना चाहिए, यदि आप उस मार्ग पर जाना चुनते हैं।)


1
यह ध्यान देने योग्य है कि पुस्तकालय संस्करण eachECMA5 विनिर्देश के समान व्यवहार नहीं करते forEachहैं, वे सभी सरणियों को घने के रूप में मानते हैं (आईई कीड़े से बचने के लिए, बशर्ते कि आप जागरूक हों)। अन्यथा "गोत्र" हो सकता है। संदर्भ के रूप में github.com/es-shims/es5-shim/issues/190
Xotic750

7
इसके अलावा कुछ प्रोटोटाइप विधियाँ हैं जो आपको ऐसा करने की अनुमति देती हैं जैसे Array.prototype.someकि आप तब तक लूप करेंगे जब तक आप एक सत्य मान वापस नहीं करते हैं या जब तक कि यह सरणी के माध्यम से पूरी तरह से लूप नहीं हो जाता है। Array.prototype.everyके समान है, Array.prototype.someलेकिन यदि आप एक मिथ्या मान लौटाते हैं तो रुक जाता है।
'17

यदि आप विभिन्न ब्राउज़रों और इस तरह के शिम पर कुछ परीक्षा परिणाम देखना चाहते हैं, तो आप यहाँ देख सकते हैं, ci.testling.com/Xotic750/util-x
Xotic750

इसके अलावा, Array.prototyp.forEach का उपयोग करने से आपके कोड को एक्सटेंशन की दया पर रखा जाएगा। उदाहरण के लिए, यदि आप एक पेज में एम्बेड किए जाने के लिए एक कोड लिख रहे हैं, तो एक मौका है कि Array.prototype.forEach को किसी अन्य चीज़ से अधिलेखित किया गया है।
मार्बल डेमन

2
@ मार्बलडैम की संभावना इतनी कम है कि यह प्रभावी रूप से असंभव है और इसलिए नगण्य है। Array.prototype.forEachकुछ गैर-संगत संस्करण के साथ ओवरराइटिंग में इतने सारे पुस्तकालयों को तोड़ने की क्षमता होगी जो इसे उस कारण से बचने के लिए वैसे भी मदद नहीं करेगा।
एलेक्सिस किंग

12

आप अपने कस्टम foreach फ़ंक्शन का उपयोग कर सकते हैं जो बेहतर प्रदर्शन करेगा फिर Array.forEach

आपको इसे एक बार अपने कोड में जोड़ना चाहिए। यह ऐरे में नया फंक्शन जोड़ेगा।

function foreach(fn) {
    var arr = this;
    var len = arr.length;
    for(var i=0; i<len; ++i) {
        fn(arr[i], i);
    }
}

Object.defineProperty(Array.prototype, 'customForEach', {
    enumerable: false,
    value: foreach
});

फिर आप इसे Array.forEach की तरह कहीं भी उपयोग कर सकते हैं

[1,2,3].customForEach(function(val, i){

});

एकमात्र अंतर यह 3 गुना तेज है। https://jsperf.com/native-arr-foreach-vs-custom-foreach

अद्यतन: नए क्रोम संस्करण में .forEach () के प्रदर्शन में सुधार किया गया था। हालांकि, समाधान अन्य ब्राउज़रों में अतिरिक्त प्रदर्शन दे सकता है।

JSPerf


4

यह कई डेवलपर्स (जैसे काइल सिम्पसन) द्वारा सुझाया गया .forEachहै कि यह इंगित करने के लिए उपयोग किया जाता है कि सरणी का साइड इफेक्ट होगा और .mapशुद्ध कार्यों के लिए। forलूप अच्छी तरह से ज्ञात लूप या किसी भी अन्य मामले के लिए एक सामान्य-उद्देश्य समाधान के रूप में अच्छी तरह से फिट होते हैं जो अधिकांश प्रोग्रामिंग भाषाओं में व्यापक समर्थन के कारण संवाद करना आसान नहीं होता है।

जैसे

/* For Loop known number of iterations */
const numberOfSeasons = 4;
for (let i = 0; i < numberOfSeasons; i++) {
  //Do Something
}

/* Pure transformation */
const arrayToBeUppercased = ['www', 'html', 'js', 'us'];
const acronyms = arrayToBeUppercased.map((el) => el.toUpperCase));

/* Impure, side-effects with .forEach */
const acronymsHolder = [];
['www', 'html', 'js', 'us'].forEach((el) => acronymsHolder.push(el.toUpperCase()));

कन्वेंशन वार, यह सबसे अच्छा लगता है, हालांकि समुदाय वास्तव में नए चलना प्रोटोकॉल for inछोरों पर एक सम्मेलन में नहीं बसता है। आम तौर पर, मुझे लगता है कि एफपी अवधारणाओं का पालन करना एक अच्छा विचार है जिसे जेएस समुदाय अपनाने के लिए खुला है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.