सवाल जावास्क्रिप्ट में एक सरणी के लिए प्रत्येक के लिए?


जावास्क्रिप्ट का उपयोग कर सरणी में सभी प्रविष्टियों के माध्यम से मैं कैसे लूप कर सकता हूं?

मैंने सोचा कि यह ऐसा कुछ था:

forEach(instance in theArray)

कहा पे theArray मेरी सरणी है, लेकिन यह गलत लगता है।


3791
2018-02-17 13:51


मूल


मैंने इसकी तलाश की, लेकिन मैंने देखा forEach  और न सिर्फ for। जैसा कि कहा गया है, सी # में यह थोड़ा अलग था, और यह मुझे उलझन में :) - Dante1986
ECMAScript & nbsp; 6 में शायद "के लिए" निर्माण होगा। देख के लिए (एमडीएन) अधिक जानकारी के लिए। आप हाल ही में फ़ायरफ़ॉक्स संस्करणों के साथ इसे आजमा सकते हैं। - Slaven Rezic
Array.ForEach जावास्क्रिप्ट में Arrays के लिए प्रत्येक के लिए () के लिए लगभग 95% धीमी है। इस प्रदर्शन परीक्षण को ऑनलाइन देखें: jsperf.com/fast-array-foreach के जरिए coderwall.com/p/kvzbpa - molokoloco
कई स्थितियों के लिए कि 9 5% धीमी महत्वपूर्ण नहीं होने वाली है blog.niftysnippets.org/2012/02/foreach-and-runtime-cost.html - David Sykes
इसके विपरीत, में अजगर यह है अधिक कुशल लूप के लिए पारंपरिक उपयोग करने के बजाय कार्यों का उपयोग करने के लिए। (उस पर विचार करे i < len तथा i++ दुभाषिया के बजाए इंजन द्वारा किया जा सकता है।) - joeytwiddle


जवाब:


टी एल; डॉ

  • उपयोग न करें for-in जब तक आप इसे सुरक्षा उपायों के साथ उपयोग नहीं करते हैं या कम से कम जानते हैं कि यह आपको क्यों काट सकता है।
  • आपके सबसे अच्छे दांव आमतौर पर होते हैं

    • for-of लूप (ES2015 + केवल),
    • Array#forEach (spec | MDN) (या इसके रिश्तेदार some और ऐसे) (ईएस 5 + केवल),
    • एक साधारण पुराने फैशन for पाश,
    • या for-in सुरक्षा के साथ।

लेकिन यहां है बहुत सारे अन्वेषण करने के लिए और अधिक पढ़ें ...


जावास्क्रिप्ट में सरणी और सरणी जैसी वस्तुओं के माध्यम से लूपिंग के लिए शक्तिशाली अर्थशास्त्र है। मैंने जवाब को दो भागों में विभाजित कर दिया है: वास्तविक सरणी के लिए विकल्प, और उन चीजों के लिए विकल्प जो केवल सरणी हैं-पसंद, जैसे arguments वस्तु, अन्य पुनरावृत्त वस्तुओं (ES2015 +), डीओएम संग्रह, और इतने पर।

मैं जल्दी से ध्यान दूंगा कि आप ES2015 विकल्पों का उपयोग कर सकते हैं अभी व, यहां तक ​​कि ES5 इंजनों पर भी transpiling ES2015 से ईएस 5। अधिक के लिए "ES2015 पारदर्शी" / "ES6 पारदर्शी" के लिए खोजें ...

ठीक है, आइए हमारे विकल्पों को देखें:

वास्तविक Arrays के लिए

आपके पास तीन विकल्प हैं ECMAScript 5 ("ES5"), इस समय सबसे व्यापक रूप से समर्थित संस्करण, और दो और जोड़े गए ECMAScript 2015 ("ES2015", "ES6"):

  1. उपयोग forEach और संबंधित (ES5 +)
  2. एक सरल प्रयोग करें for पाश
  3. उपयोग for-in  सही ढंग से
  4. उपयोग for-of (निहित रूप से एक इटरेटर का उपयोग करें) (ES2015 +)
  5. एक इटरेटर स्पष्ट रूप से उपयोग करें (ES2015 +)

विवरण:

1. प्रयोग करें forEach और संबंधित

किसी भी अस्पष्ट-आधुनिक वातावरण में (इसलिए, IE8 नहीं) जहां आपके पास पहुंच है Array ईएस 5 (सीधे या पॉलीफिल का उपयोग करके) द्वारा जोड़ा गया विशेषताएं, आप इसका उपयोग कर सकते हैं forEach (spec | MDN):

var a = ["a", "b", "c"];
a.forEach(function(entry) {
    console.log(entry);
});

forEach कॉलबैक फ़ंक्शन स्वीकार करता है और वैकल्पिक रूप से, उपयोग करने के लिए एक मान स्वीकार करता है this उस कॉलबैक को कॉल करते समय (ऊपर उपयोग नहीं किया गया)। कॉलबैक को सरणी में प्रत्येक प्रविष्टि के लिए बुलाया जाता है, क्रम में, स्पैस सरणी में मौजूद मौजूदा प्रविष्टियों को छोड़ना। यद्यपि मैंने केवल ऊपर एक तर्क का उपयोग किया है, कॉलबैक को तीन के साथ बुलाया जाता है: प्रत्येक प्रविष्टि का मान, उस प्रविष्टि की अनुक्रमणिका, और जिस सरणी पर आप पुनरावृत्त कर रहे हैं उसका संदर्भ (यदि आपके फ़ंक्शन में पहले से ही यह आसान नहीं है )।

जब तक आप IE8 जैसे अप्रचलित ब्राउज़र का समर्थन नहीं कर रहे हैं (जो सितंबर 2016 में इस लेखन के रूप में नेटएपस 4% से अधिक बाजार हिस्सेदारी पर दिखाता है), तो आप खुशी से उपयोग कर सकते हैं forEach बिना किसी शिम के एक सामान्य उद्देश्य के वेब पेज में। यदि आपको अप्रचलित ब्राउज़र, shimming / polyfilling का समर्थन करने की आवश्यकता है forEach आसानी से किया जा सकता है (कई विकल्पों के लिए "es5 shim" के लिए खोजें)।

forEach इसका लाभ यह है कि आपको उस क्षेत्र में इंडेक्सिंग और वैल्यू वेरिएबल्स घोषित करने की आवश्यकता नहीं है, क्योंकि उन्हें पुनरावृत्ति समारोह में तर्क के रूप में आपूर्ति की जाती है, और इतनी अच्छी तरह से उस पुनरावृत्ति के लिए अच्छी तरह से स्कॉप्ड किया जाता है।

यदि आप प्रत्येक सरणी प्रविष्टि के लिए फ़ंक्शन कॉल करने की रनटाइम लागत के बारे में चिंतित हैं, तो मत बनें; विवरण

साथ ही, forEach "उन सभी के माध्यम से लूप" फ़ंक्शन है, लेकिन ईएस 5 ने कई अन्य उपयोगी "सरणी के माध्यम से अपना काम करें और काम करें" कार्यों को परिभाषित किया है, जिनमें निम्न शामिल हैं:

  • every (कॉलबैक रिटर्न पहली बार लूपिंग बंद कर देता है false या कुछ झूठा)
  • some (कॉलबैक रिटर्न पहली बार लूपिंग बंद कर देता है true या कुछ सच)
  • filter (तत्वों सहित एक नई सरणी बनाता है जहां फ़िल्टर फ़ंक्शन देता है true और उन लोगों को छोड़कर जहां यह लौटता है false)
  • map (कॉलबैक द्वारा दिए गए मानों से एक नई सरणी बनाता है)
  • reduce (पिछली मानों में गुजरने, कॉलबैक को बार-बार कॉल करके एक मान बनाता है; विवरण के लिए spec देखें; एक सरणी की सामग्री को सूचीबद्ध करने के लिए उपयोगी और कई अन्य चीजें)
  • reduceRight (पसंद reduce, लेकिन आरोही क्रम के बजाय अवरोही में काम करता है)

2. एक सरल का प्रयोग करें for पाश

कभी-कभी पुराने तरीके सर्वश्रेष्ठ होते हैं:

var index;
var a = ["a", "b", "c"];
for (index = 0; index < a.length; ++index) {
    console.log(a[index]);
}

यदि लूप के दौरान सरणी की लंबाई नहीं बदलेगी, और यह प्रदर्शन-संवेदी कोड (संभावना नहीं है) में है, तो आगे की लंबाई को पकड़ने वाला थोड़ा और जटिल संस्करण हो सकता है छोटे थोड़ा तेज़:

var index, len;
var a = ["a", "b", "c"];
for (index = 0, len = a.length; index < len; ++index) {
    console.log(a[index]);
}

और / या पिछड़ा गिनती:

var index;
var a = ["a", "b", "c"];
for (index = a.length - 1; index >= 0; --index) {
    console.log(a[index]);
}

लेकिन आधुनिक जावास्क्रिप्ट इंजनों के साथ, यह दुर्लभ है कि आपको रस के आखिरी बिट को बाहर निकालना होगा।

ES2015 और उच्चतर में, आप अपनी अनुक्रमणिका और मूल्य चर स्थानीय को बना सकते हैं for पाश:

let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
    let value = a[index];
}
//console.log(index); // Would cause "ReferenceError: index is not defined"
//console.log(value); // Would cause "ReferenceError: value is not defined"

और जब आप ऐसा करते हैं, न सिर्फ value लेकिन index प्रत्येक पाश पुनरावृत्ति के लिए पुनर्निर्मित किया जाता है, जिसका मतलब है कि लूप बॉडी में बनाए गए बंदरगाहों का संदर्भ है index (तथा value) उस विशिष्ट पुनरावृत्ति के लिए बनाया गया:

let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
    divs[index].addEventListener('click', e => {
        alert("Index is: " + index);
    });
}

यदि आपके पास पांच divs थे, तो आपको "इंडेक्स है: 0" मिलेगा यदि आपने पहले क्लिक किया था और "इंडेक्स है: 4" अगर आपने आखिरी बार क्लिक किया था। यह करता है नहीं यदि आप उपयोग करते हैं तो काम करें var के बजाय let

3. प्रयोग करें for-in  सही ढंग से

आप लोग आपको उपयोग करने के लिए कहेंगे for-in, परंतु वह नहीं है for-in के लिए हैfor-in के माध्यम से loops किसी ऑब्जेक्ट की संख्यात्मक गुण, एक सरणी के सूचकांक नहीं। आदेश की गारंटी नहीं है, ES2015 (ES6) में भी नहीं। ES2015 गुणों को ऑब्जेक्ट करने के लिए एक आदेश परिभाषित करता है (के माध्यम से [[OwnPropertyKeys]], [[Enumerate]], और चीजें जो उन्हें पसंद करती हैं Object.getOwnPropertyKeys), पर यह नहीं करता इसे परिभाषित करें for-in उस आदेश का पालन करेंगे। (विवरण में यह दूसरा जवाब है।)

फिर भी, यह कर सकते हैं विशेष रूप से के लिए उपयोगी हो विरल सरणियों, यदि आप उचित सुरक्षा उपाय का उपयोग करते हैं:

// `a` is a sparse array
var key;
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (key in a) {
    if (a.hasOwnProperty(key)  &&        // These are explained
        /^0$|^[1-9]\d*$/.test(key) &&    // and then hidden
        key <= 4294967294                // away below
        ) {
        console.log(a[key]);
    }
}

दो चेक नोट करें:

  1. उस वस्तु का है अपना उस नाम से संपत्ति (जिसे वह अपने प्रोटोटाइप से प्राप्त नहीं करता है), और

  2. यह कुंजी अपने सामान्य स्ट्रिंग फॉर्म में बेस -10 न्यूमेरिक स्ट्रिंग है और इसका मान <= 2 ^ 32 - 2 है (जो 4,294,967,294 है)। वह संख्या कहां से आती है? यह एक सरणी सूचकांक की परिभाषा का हिस्सा है विनिर्देश में। अन्य संख्याएं (गैर-पूर्णांक, नकारात्मक संख्याएं, 2 ^ 32 - 2 से अधिक संख्या) सरणी अनुक्रमणिका नहीं हैं। इसका कारण 2 ^ 32 है - 2 यह है कि सबसे बड़ा सूचकांक मान 2 ^ 32 से कम है - 1, जो सरणी का अधिकतम मान है length हो सकता है। (उदा।, सरणी की लंबाई 32-बिट हस्ताक्षरित पूर्णांक में फिट बैठती है।) (एक टिप्पणी में इंगित करने के लिए रॉब को प्रॉप्स मेरे ब्लॉग पोस्ट पर कि मेरा पिछला परीक्षण बिल्कुल सही नहीं था।)

यह अधिकांश सरणी पर प्रति लूप पुनरावृत्ति के अतिरिक्त ओवरहेड का एक छोटा सा हिस्सा है, लेकिन यदि आपके पास है विरल सरणी, यह लूप के लिए एक और अधिक प्रभावी तरीका हो सकता है क्योंकि यह केवल उन प्रविष्टियों के लिए लूप करता है जो वास्तव में मौजूद हैं। उदा।, उपरोक्त सरणी के लिए, हम कुल तीन बार लूप करते हैं (कुंजी के लिए "0", "10", तथा "10000"- याद रखें, वे तार हैं), 10,001 बार नहीं।

अब, आप हर बार लिखना नहीं चाहेंगे, इसलिए आप इसे अपने टूलकिट में डाल सकते हैं:

function arrayHasOwnIndex(array, prop) {
    return array.hasOwnProperty(prop) && /^0$|^[1-9]\d*$/.test(prop) && prop <= 4294967294; // 2^32 - 2
}

और फिर हम इसका इस्तेमाल इस तरह करेंगे:

for (key in a) {
    if (arrayHasOwnIndex(a, key)) {
        console.log(a[key]);
    }
}

या यदि आप केवल "अधिकांश मामलों के लिए पर्याप्त" परीक्षण में रूचि रखते हैं, तो आप इसका उपयोग कर सकते हैं, लेकिन जब यह बंद हो, तो यह बिल्कुल सही नहीं है:

for (key in a) {
    // "Good enough" for most cases
    if (String(parseInt(key, 10)) === key && a.hasOwnProperty(key)) {
        console.log(a[key]);
    }
}

4. प्रयोग करें for-of (निहित रूप से एक इटरेटर का उपयोग करें) (ES2015 +)

ES2015 जोड़ता है iterators जावास्क्रिप्ट के लिए। इटरेटर्स का उपयोग करने का सबसे आसान तरीका नया है for-of बयान। यह इस तरह दिख रहा है:

var val;
var a = ["a", "b", "c"];
for (val of a) {
    console.log(val);
}

आउटपुट:

ए
ख
सी

कवर के तहत, यह एक हो जाता है इटरेटर सरणी से और इसके माध्यम से लूप, इससे मूल्य प्राप्त करना। इसका उपयोग करने वाली समस्या नहीं है for-in है, क्योंकि यह ऑब्जेक्ट (सरणी) द्वारा परिभाषित एक इटरेटर का उपयोग करता है, और सरणी परिभाषित करती हैं कि उनके इटरेटर उनके माध्यम से फिर से चलते हैं प्रविष्टियों (उनकी संपत्ति नहीं)। भिन्न for-in ईएस 5 में, जिस क्रम में प्रविष्टियों का दौरा किया जाता है वह उनके सूचकांक का अंकीय क्रम है।

5. एक इटरेटर स्पष्ट रूप से उपयोग करें (ES2015 +)

कभी-कभी, आप एक इटरेटर का उपयोग करना चाह सकते हैं स्पष्ट रूप से। आप यह भी कर सकते हैं, हालांकि यह बहुत अधिक उलझन में है for-of। यह इस तरह दिख रहा है:

var a = ["a", "b", "c"];
var it = a.values();
var entry;
while (!(entry = it.next()).done) {
    console.log(entry.value);
}

इटेटरेटर विनिर्देश में इटरेटर परिभाषा से मेल खाता एक ऑब्जेक्ट है। आईटी इस next विधि एक नया लौटाता है परिणाम वस्तु प्रत्येक बार जब आप इसे कॉल करते हैं। परिणाम वस्तु में एक संपत्ति है, done, हमें बता रहा है कि यह किया गया है, और एक संपत्ति value उस पुनरावृत्ति के मूल्य के साथ। (done वैकल्पिक होगा अगर यह होगा false, value वैकल्पिक होगा अगर यह होगा undefined।)

इसका मतलब value इटरेटर पर निर्भर करता है; सरणी समर्थन (कम से कम) तीन कार्यों जो iterators वापस:

  • values(): यह वह है जिसे मैंने ऊपर इस्तेमाल किया था। यह एक इटेटरेटर देता है जहां प्रत्येक value उस पुनरावृत्ति के लिए सरणी प्रविष्टि है ("a", "b", तथा "c" पहले उदाहरण में)।
  • keys(): प्रत्येक इटेटरेटर देता है जहां प्रत्येक value उस पुनरावृत्ति के लिए कुंजी है (इसलिए हमारे लिए a ऊपर, वह होगा "0", फिर "1", फिर "2")।
  • entries(): प्रत्येक इटेटरेटर देता है जहां प्रत्येक value रूप में एक सरणी है [key, value] उस पुनरावृत्ति के लिए।

ऐरे-लाइक ऑब्जेक्ट्स के लिए

सच्चे सरणी के अलावा, भी हैं सरणी की तरह ऑब्जेक्ट्स जिनमें एक है length संख्यात्मक नाम वाले संपत्ति और गुण: NodeList उदाहरण, द arguments वस्तु, आदि। हम उनकी सामग्री के माध्यम से कैसे लूप करते हैं?

सरणी के लिए ऊपर दिए गए विकल्पों में से किसी एक का प्रयोग करें

कम से कम कुछ, और संभावित रूप से सबसे अधिक या यहां तक ​​कि सभी, सरणी दृष्टिकोणों के ऊपर अक्सर ऑब्जेक्ट जैसी वस्तुओं के बराबर अच्छी तरह से लागू होते हैं:

  1. उपयोग forEach और संबंधित (ES5 +)

    पर विभिन्न कार्यों Array.prototype "जानबूझकर सामान्य" हैं और आमतौर पर सरणी जैसी वस्तुओं पर उपयोग किया जा सकता है Function#call या Function#apply। (देखें मेजबान द्वारा प्रदान की गई वस्तुओं के लिए चेतावनी इस उत्तर के अंत में, लेकिन यह एक दुर्लभ मुद्दा है।)

    मान लीजिए कि आप उपयोग करना चाहते थे forEach पर Nodeकी childNodes संपत्ति। आप यह करेंगे:

    Array.prototype.forEach.call(node.childNodes, function(child) {
        // Do something with `child`
    });
    

    यदि आप ऐसा करने जा रहे हैं, तो आप पुन: उपयोग के लिए एक चर में फ़ंक्शन संदर्भ की प्रतिलिपि लेना चाहेंगे, उदाहरण:

    // (This is all presumably in some scoping function)
    var forEach = Array.prototype.forEach;
    
    // Then later...
    forEach.call(node.childNodes, function(child) {
        // Do something with `child`
    });
    
  2. एक सरल प्रयोग करें for पाश

    जाहिर है, एक साधारण for लूप सरणी जैसी वस्तुओं पर लागू होता है।

  3. उपयोग for-in  सही ढंग से

    for-in एक ही सरसों के साथ एक सरणी के साथ सरणी जैसी वस्तुओं के साथ काम करना चाहिए; उपरोक्त # 1 पर होस्ट-प्रदान की गई वस्तुओं के लिए चेतावनी लागू हो सकती है।

  4. उपयोग for-of (निहित रूप से एक इटरेटर का उपयोग करें) (ES2015 +)

    for-of वस्तु (यदि कोई हो) द्वारा प्रदान किए गए इटरेटर का उपयोग करेगा; हमें यह देखना होगा कि यह विभिन्न सरणी जैसी वस्तुओं, विशेष रूप से होस्ट-प्रदान किए गए लोगों के साथ कैसे खेलता है। उदाहरण के लिए, के लिए विनिर्देश NodeList से querySelectorAll पुनरावृत्ति का समर्थन करने के लिए अद्यतन किया गया था। के लिए कल्पना HTMLCollection से getElementsByTagName नहीं था।

  5. एक इटरेटर स्पष्ट रूप से उपयोग करें (ES2015 +)

    # 4 देखें, हमें देखना होगा कि इटेटरेटर कैसे खेलते हैं।

एक सच्ची सरणी बनाएँ

अन्य बार, आप एक सरणी जैसी वस्तु को एक वास्तविक सरणी में परिवर्तित करना चाहते हैं। ऐसा करना आश्चर्यजनक रूप से आसान है:

  1. उपयोग slice सरणी की विधि

    हम इसका उपयोग कर सकते हैं slice सरणी की विधि, जो ऊपर वर्णित अन्य विधियों की तरह है "जानबूझकर जेनेरिक" है और इसलिए सरणी जैसी वस्तुओं के साथ इसका उपयोग किया जा सकता है, जैसे:

    var trueArray = Array.prototype.slice.call(arrayLikeObject);
    

    तो उदाहरण के लिए, अगर हम एक कन्वर्ट करना चाहते हैं NodeList एक सच्ची सरणी में, हम यह कर सकते हैं:

    var divs = Array.prototype.slice.call(document.querySelectorAll("div"));
    

    देखें मेजबान द्वारा प्रदान की गई वस्तुओं के लिए चेतावनी नीचे। विशेष रूप से, ध्यान दें कि यह IE8 और इससे पहले में विफल हो जाएगा, जो आपको होस्ट-प्रदत्त ऑब्जेक्ट्स का उपयोग करने की अनुमति नहीं देता है this उसके जैसा।

  2. उपयोग सिंटैक्स फैलाएं (...)

    ES2015 का उपयोग करना भी संभव है सिंटैक्स फैलाओ इस सुविधा का समर्थन करने वाले जावास्क्रिप्ट इंजन के साथ:

    var trueArray = [...iterableObject];
    

    तो उदाहरण के लिए, अगर हम एक कन्वर्ट करना चाहते हैं NodeList एक सच्चे सरणी में, फैलाव वाक्यविन्यास के साथ यह काफी संक्षिप्त हो जाता है:

    var divs = [...document.querySelectorAll("div")];
    
  3. उपयोग Array.from  (कल्पना) | (MDN)

    Array.from (ES2015 +, लेकिन आसानी से polyfilled) एक सरणी जैसी वस्तु से एक सरणी बनाता है, वैकल्पिक रूप से पहले मैपिंग फ़ंक्शन के माध्यम से प्रविष्टियों को पारित करता है। इसलिए:

    var divs = Array.from(document.querySelectorAll("div"));
    

    या यदि आप किसी दिए गए वर्ग के तत्वों के टैग नामों की सरणी प्राप्त करना चाहते हैं, तो आप मैपिंग फ़ंक्शन का उपयोग करेंगे:

    // Arrow function (ES2015):
    var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName);
    
    // Standard function (since `Array.from` can be shimmed):
    var divs = Array.from(document.querySelectorAll(".some-class"), function(element) {
        return element.tagName;
    });
    

मेजबान द्वारा प्रदान की गई वस्तुओं के लिए चेतावनी

यदि तुम प्रयोग करते हो Array.prototype के साथ काम करता है होस्ट द्वारा प्रदत्त सरणी जैसी वस्तुओं (डीओएम सूचियों और जावास्क्रिप्ट इंजन की बजाय ब्राउज़र द्वारा प्रदान की जाने वाली अन्य चीजें), आपको यह सुनिश्चित करने के लिए अपने लक्षित वातावरण में परीक्षण करना सुनिश्चित करना होगा कि मेजबान द्वारा प्रदान की गई वस्तु ठीक से व्यवहार करे। ज्यादातर सही तरीके से व्यवहार करते हैं (अब), लेकिन परीक्षण करना महत्वपूर्ण है। कारण यह है कि अधिकांश Array.prototype विधियों का उपयोग करने की संभावना है जो होस्ट-प्रदत्त ऑब्जेक्ट पर भरोसा करते हैं, जो अमूर्त को ईमानदार उत्तर देते हैं [[HasProperty]] ऑपरेशन। इस लेखन के अनुसार, ब्राउज़र इस का बहुत अच्छा काम करते हैं, लेकिन 5.1 spec ने संभावना के लिए अनुमति दी है कि होस्ट-प्रदान की गई वस्तु ईमानदार नहीं हो सकती है। वह अंदर है §8.6.2, उस खंड की शुरुआत के पास बड़ी तालिका के नीचे कई पैराग्राफ), जहां यह कहता है:

होस्ट ऑब्जेक्ट्स इन आंतरिक तरीकों को किसी भी तरीके से लागू नहीं कर सकते हैं जब तक अन्यथा निर्दिष्ट नहीं किया जाता है; उदाहरण के लिए, एक संभावना यह है कि [[Get]] तथा [[Put]] एक विशेष होस्ट ऑब्जेक्ट के लिए वास्तव में संपत्ति मूल्यों को लाता है और स्टोर करता है लेकिन [[HasProperty]] हमेशा उत्पन्न करता है असत्य

(मुझे ES2015 spec में समतुल्य शब्दकोष नहीं मिल सका, लेकिन यह अभी भी मामला होना बाध्य है।) फिर से, इस पुस्तक के रूप में आधुनिक ब्राउज़र में सामान्य होस्ट-प्रदान की गई सरणी जैसी वस्तुओं [NodeList उदाहरण के लिए उदाहरण कर संभालना [[HasProperty]] सही ढंग से, लेकिन परीक्षण करना महत्वपूर्ण है।)


5980
2018-02-17 13:53



मैं इसे भी जोड़ना चाहूंगा .forEach कुशलता से तोड़ा नहीं जा सकता है। आपको ब्रेक करने के लिए अपवाद फेंकना होगा। - Pijusn
@ पायस: यदि आप लूप को तोड़ना चाहते हैं, तो आप इसका उपयोग कर सकते हैं some। (मैं तोड़ने की इजाजत देना पसंद करता forEach साथ ही, लेकिन वे, उम, मुझसे नहीं पूछा था। ;-)) - T.J. Crowder
@ टीजे क्रॉडर सच है, भले ही यह एक काम की तरह दिखता है क्योंकि यह इसका प्राथमिक उद्देश्य नहीं है। - Pijusn
@ user889030: आपको एक चाहिए , बाद k=0, नहीं ;। याद रखें, प्रोग्रामिंग कई चीजें हैं, जिनमें से एक विस्तार से नज़दीक है ... :-) - T.J. Crowder
@JimB: यह ऊपर कवर किया गया है (और length एक विधि नहीं है)। :-) - T.J. Crowder


संपादित करें: यह जवाब निराशाजनक रूप से पुराना है। एक और आधुनिक दृष्टिकोण के लिए, देखो एक सरणी पर उपलब्ध विधियों। ब्याज के तरीके हो सकते हैं:

  • प्रत्येक के लिए
  • नक्शा
  • फिल्टर
  • ज़िप
  • को कम
  • प्रत्येक
  • कुछ

एक सरणी को फिर से चलाने का मानक तरीका जावास्क्रिप्ट एक वेनिला है for-loop:

var length = arr.length,
    element = null;
for (var i = 0; i < length; i++) {
  element = arr[i];
  // Do something with element i.
}

नोट, हालांकि, यह दृष्टिकोण केवल तभी अच्छा है जब आपके पास घना सरणी हो, और प्रत्येक अनुक्रमणिका किसी तत्व द्वारा कब्जा कर लिया जाता है। यदि सरणी स्पैस है, तो आप इस दृष्टिकोण के साथ प्रदर्शन समस्याओं में भाग ले सकते हैं, क्योंकि आप बहुत सारे सूचकांकों को फिर से शुरू करेंगे जो नहीं करते हैं वास्तव में सरणी में मौजूद है। इस मामले में, ए for .. in-लोप एक बेहतर विचार हो सकता है। तथापि, आपको यह सुनिश्चित करने के लिए उपयुक्त सुरक्षा उपायों का उपयोग करना होगा कि केवल सरणी (यानी, सरणी तत्व) की वांछित गुणों पर कार्य किया जाए, क्योंकि for..in-लोप को विरासत ब्राउज़र में भी समझा जाएगा, या यदि अतिरिक्त गुणों को परिभाषित किया गया है enumerable

में ईसीएमएस्क्रिप्ट 5 सरणी प्रोटोटाइप पर प्रत्येक विधि के लिए एक होगा, लेकिन यह विरासत ब्राउज़र में समर्थित नहीं है। इसलिए इसे लगातार उपयोग करने में सक्षम होने के लिए आपके पास या तो एक ऐसा वातावरण होना चाहिए जो इसका समर्थन करता है (उदाहरण के लिए, Node.js सर्वर साइड जावास्क्रिप्ट के लिए), या "पॉलीफिल" का उपयोग करें। हालांकि, इस कार्यक्षमता के लिए पॉलीफिल छोटा है और चूंकि यह कोड को पढ़ने में आसान बनाता है, यह शामिल करने के लिए एक अच्छा पॉलीफिल है।


451
2018-02-17 13:55



यही वजह है कि for(instance in objArray)  सही उपयोग नहीं है? यह मेरे लिए अधिक आसान लग रहा है, लेकिन मैंने सुना है कि आप इसके बारे में बात करते हैं क्योंकि उपयोग के लिए सही तरीका नहीं है? - Dante1986
आप इनलाइन लम्बाई कैशिंग का उपयोग कर सकते हैं: (var i = 0, l = arr.length; i <l; i ++) - Robert
क्या पहली पंक्ति के अंत में अल्पविराम है, या यह एक टाइपो है (अर्धविराम हो सकता है)? - 9KSoft
@ वर्धा-वेब यह जानबूझकर है। यह हमें एकल के साथ कई चर घोषित करने में सक्षम बनाता है var-keyword। अगर हमने अर्धविराम का इस्तेमाल किया था, तो element वैश्विक दायरे में घोषित किया गया होगा (या, बल्कि जेएसहिंट उत्पादन तक पहुंचने से पहले हमारे ऊपर चिल्लाया होगा)। - PatrikAkerstrand


यदि आप इसका उपयोग कर रहे हैं jQuery पुस्तकालय, आप उपयोग कर सकते हैं jQuery.each:

$.each(yourArray, function(index, value) {
  // do your stuff here
});

संपादित करें: 

प्रश्न के अनुसार, उपयोगकर्ता jquery के बजाय जावास्क्रिप्ट में कोड चाहते हैं ताकि संपादन हो

var length = yourArray.length;   
for (var i = 0; i < length; i++) {
  // Do something with yourArray[i].
}

205
2018-02-17 14:01



मैं शायद इस जवाब का सबसे अधिक उपयोग करने जा रहा हूं। यह सवाल का सबसे अच्छा जवाब नहीं है, लेकिन व्यावहारिक रूप से jQuery का उपयोग कर हमारे लिए सबसे सरल और सबसे अधिक लागू होगा। मुझे लगता है कि हमें सभी को वेनिला मार्ग भी सीखना चाहिए। यह आपकी समझ का विस्तार करने के लिए कभी दर्द नहीं होता है। - mopsyd
बस इसके लिए: jQuery प्रत्येक बहुत धीमी तो देशी समाधान है। जब भी यह संभव हो, jQuery की बजाय मूल जावास्क्रिप्ट का उपयोग करने के लिए jQuery द्वारा सलाह दी जाती है। jsperf.com/browser-diet-jquery-each-vs-for-loop - Kevin Boss
जब आप वेनिला जेएस का उपयोग कर सकते हैं तो jQuery का उपयोग करने से बचें - Noe
मानक जेएस पर चिपकाएं, तीसरे पक्ष के पुस्तकालयों को उत्तर से बाहर रखें जब तक कोई मूल भाषा समाधान न हो - Steve K
मुझे इस तरह की याद दिलाता है: i.stack.imgur.com/ssRUr.gif - Ajedi32


पीछे लूप

मुझे लगता है उलटा लूप के लिए यहां एक उल्लेख का हकदार है:

for (var i = array.length; i--; ) {
     // process array[i]
}

लाभ:

  • आपको अस्थायी घोषित करने की आवश्यकता नहीं है len परिवर्तनीय, या के खिलाफ तुलना करें array.length प्रत्येक पुनरावृत्ति पर, इनमें से कोई भी एक मिनट अनुकूलन हो सकता है।
  • भाई बहन को हटा रहा है रिवर्स ऑर्डर में डीओएम से आमतौर पर होता है अधिक कुशल। (ब्राउजर को अपने आंतरिक सरणी में तत्वों को कम स्थानांतरित करने की आवश्यकता है।)
  • अगर तुम सरणी को संशोधित करें जबकि इंडेक्स पर या उसके बाद लूपिंग मैं (उदाहरण के लिए आप एक आइटम को हटा या डालें array[i]), तो एक फॉरवर्ड लूप उस आइटम को छोड़ देगा जो बाईं ओर स्थिति में स्थानांतरित हो जाता है मैं, या फिर से संसाधित करें मैंवें आइटम जो सही स्थानांतरित किया गया था। लूप के लिए पारंपरिक में, आप सकता है अद्यतन करें मैं प्रसंस्करण की आवश्यकता वाले अगले आइटम को इंगित करने के लिए - 1, लेकिन पुनरावृत्ति की दिशा को उलटना अक्सर एक होता है सरल तथा अधिक सुरुचिपूर्ण समाधान
  • इसी तरह, जब संशोधित या हटाते हैं नेस्ट डीओएम तत्व, रिवर्स कैन में प्रसंस्करण कर सकते हैं त्रुटियों को बाधित करें। उदाहरण के लिए, अपने बच्चों को संभालने से पहले माता-पिता नोड के आंतरिक HTML को संशोधित करने पर विचार करें। जब तक बच्चा नोड पहुंचाया जाता है तब तक इसे डीओएम से अलग किया जाएगा, जिसे नवजात शिशु द्वारा प्रतिस्थापित किया गया है जब माता-पिता का आंतरिक HTML लिखा गया था।
  • यह है कम टाइप करने के लिए, और पढ़ना, उपलब्ध कुछ अन्य विकल्पों की तुलना में। हालांकि यह खो देता है forEach() और ईएस 6 के लिए for ... of

नुकसान:

  • यह वस्तुओं को रिवर्स ऑर्डर में संसाधित करता है। यदि आप परिणामों से एक नई सरणी बना रहे थे, या स्वाभाविक रूप से स्क्रीन पर चीजों को प्रिंट कर रहे थे आउटपुट उलट दिया जाएगा मूल आदेश के संबंध में।
  • अपने आदेश को बनाए रखने के लिए बार-बार बच्चे को भाई बहन को पहले बच्चे के रूप में डालना कम सक्षम। (ब्राउजर सही चीजों को स्थानांतरित करना जारी रखेगा।) डोम नोड्स को कुशलतापूर्वक बनाने के लिए और क्रम में, केवल लूप आगे बढ़ें और सामान्य के रूप में संलग्न करें (और "दस्तावेज़ खंड" का भी उपयोग करें)।
  • रिवर्स लूप है भ्रामक जूनियर डेवलपर्स के लिए। (आप अपने दृष्टिकोण के आधार पर एक लाभ पर विचार कर सकते हैं।)

क्या मुझे हमेशा इसका इस्तेमाल करना चाहिए?

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

हालांकि प्रदर्शन लाभ आमतौर पर महत्वहीन होते हैं, यह चिल्लाने की तरह है:

"बस सूची में हर आइटम के लिए यह करो, मुझे आदेश की परवाह नहीं है!"

हालांकि अभ्यास में है नहीं वास्तव में इरादे का एक विश्वसनीय संकेत, क्योंकि यह उन अवसरों से अलग नहीं है जब आप कर आदेश के बारे में परवाह है, और वास्तव में करते हैं जरुरत रिवर्स में लूप करने के लिए। तो वास्तव में "देखभाल न करें" इरादे को सटीक रूप से व्यक्त करने के लिए एक और निर्माण की आवश्यकता होगी, वर्तमान में ईसीएमएस्क्रिप्ट सहित अधिकांश भाषाओं में अनुपलब्ध कुछ, लेकिन जिसे कहा जा सकता है, उदाहरण के लिए, forEachUnordered()

अगर आदेश कोई फर्क नहीं पड़ता, और दक्षता एक चिंता है (एक गेम या एनीमेशन इंजन के सबसे निचले लूप में), तो यह आपके गो-टू पैटर्न के रूप में लूप के रिवर्स का उपयोग करने के लिए स्वीकार्य हो सकता है। बस याद रखें कि मौजूदा कोड में लूप के लिए एक रिवर्स देख रहा है जरूरी नहीं है आदेश अप्रासंगिक है!

प्रत्येक के लिए उपयोग करना बेहतर है ()

सामान्य रूप से उच्च स्तर कोड के लिए जहां स्पष्टता और सुरक्षा अधिक चिंताएं हैं, मैं उपयोग करने की सिफारिश करेंगे Array::forEach आपके डिफ़ॉल्ट पैटर्न के रूप में:

  • यह पढ़ने के लिए स्पष्ट है।
  • यह इंगित करता है कि मैं ब्लॉक के भीतर स्थानांतरित नहीं किया जा रहा है (जो हमेशा लंबे समय तक छुपा एक संभावित आश्चर्य है for तथा while लूप।)
  • यह आपको बंद करने के लिए एक मुफ्त दायरा देता है।
  • यह स्थानीय चर के रिसाव और बाहरी चर के साथ आकस्मिक टक्कर (और उत्परिवर्तन) को कम कर देता है।

फिर जब आप अपने कोड में लूप के लिए रिवर्स देखते हैं, तो यह एक संकेत है कि इसे एक अच्छे कारण (शायद ऊपर वर्णित कारणों में से एक) के लिए उलट दिया जाता है। और लूप के लिए पारंपरिक आगे देखने से संकेत मिलता है कि स्थानांतरण हो सकता है।

(यदि इरादे की चर्चा आपको कोई समझ नहीं देती है, तो आपको और आपके कोड को क्रॉकफोर्ड के व्याख्यान को देखने से लाभ हो सकता है प्रोग्रामिंग शैली और आपका दिमाग।)


यह कैसे काम करता है?

for (var i = 0; i < array.length; i++) { ... }   // Forwards

for (var i = array.length; i--; )    { ... }   // Reverse

आप उसे नोटिस करेंगे i-- मध्य खंड है (जहां हम आमतौर पर तुलना देखते हैं) और अंतिम खंड खाली है (जहां हम आमतौर पर देखते हैं i++)। इसका मतलब है कि i-- के रूप में भी प्रयोग किया जाता है शर्त निरंतरता के लिए। महत्वपूर्ण रूप से, इसे निष्पादित और चेक किया जाता है से पहले प्रत्येक पुनरावृत्ति।

  • यह कैसे शुरू हो सकता है array.length विस्फोट के बिना?

    इसलिये i-- रन से पहले प्रत्येक पुनरावृत्ति, पहले पुनरावृत्ति पर हम वास्तव में आइटम तक पहुंच पाएंगे array.length - 1 जो किसी भी मुद्दे से परहेज करता है सरणी-आउट-ऑफ-सीमा  undefined आइटम नहीं है।

  • इंडेक्स 0 से पहले यह फिर से क्यों नहीं रोकता है?

    स्थिति जब लूप फिर से शुरू हो जाएगा i-- एक झूठे मूल्य का मूल्यांकन करता है (जब यह 0 उत्पन्न करता है)।

    यह चाल है कि विपरीत है --iपीछे की ओर i-- ऑपरेटर कमी i लेकिन मूल्य पैदा करता है से पहले कमी आपका कंसोल इसे प्रदर्शित कर सकता है:

    > var i = 5; [i, i--, i];

    [5, 5, 4]

    तो अंतिम पुनरावृत्ति पर, मैं पहले था 1 और यह i-- अभिव्यक्ति इसे बदलती है 0 लेकिन वास्तव में पैदावार 1 (सच्चाई), और इसलिए स्थिति गुजरती है। अगले पुनरावृत्ति पर i-- परिवर्तन मैं सेवा मेरे -1 लेकिन पैदावार 0 (झूठी), लूप के नीचे से तुरंत बाहर निकलने के लिए निष्पादन का कारण बनता है।

    लूप के लिए पारंपरिक आगे में, i++ तथा ++i अदलाबदल करने योग्य हैं (डगलस क्रॉकफोर्ड बताते हैं)। हालांकि लूप के विपरीत में, क्योंकि हमारी कमी भी हमारी हालत अभिव्यक्ति है, हमें साथ रहना चाहिए i-- अगर हम इंडेक्स 0 पर आइटम को संसाधित करना चाहते हैं।


सामान्य ज्ञान

कुछ लोग रिवर्स में थोड़ा तीर खींचना पसंद करते हैं for लूप, और एक विंक के साथ अंत:

for (var i = array.length; i --> 0 ;) {

मुझे लूप के रिवर्स के लाभ और भय दिखाने के लिए डब्ल्यूवाईएल में क्रेडिट जाते हैं।


88
2018-05-02 14:21



मैं जोड़ना भूल गया बेंचमार्क। मैं यह भी उल्लेख करना भूल गया कि रिवर्स लूपिंग 6502 जैसे 8-बिट प्रोसेसर पर एक महत्वपूर्ण अनुकूलन है, जहां आपको वास्तव में मुफ्त में तुलना मिलती है! - joeytwiddle
रिवर्स लूप के लिए इसके बारे में कैसे? var i = array.length; मैं जबकि--) { ... - Kabb5
क्षमा करें @ Kabb5 मैं AFK था। हां कि लूप काफी स्पष्ट और अनिवार्य रूप से वही है। - joeytwiddle
आह, अच्छा पुराना "तीर और एक विंक" कोड पैटर्न। मुझे यह पसंद है! मेरे द्वारा +1! - Matheus Avellar
वही जवाब बहुत अधिक संक्षेप में दिया जाता है यहाँ (एक अलग सवाल पर)। - joeytwiddle


कुछ सीस्टाइल भाषा का उपयोग करें foreach गणना के माध्यम से लूप करने के लिए। जावास्क्रिप्ट में यह किया जाता है for..in लूप संरचना:

var index,
    value;
for (index in obj) {
    value = obj[index];
}

कुछ पकड़ा गया है। for..in ऑब्जेक्ट के प्रत्येक संख्या के सदस्यों और उसके प्रोटोटाइप पर सदस्यों के माध्यम से लूप होगा। ऑब्जेक्ट के प्रोटोटाइप के माध्यम से विरासत में प्राप्त मूल्यों को पढ़ने से बचने के लिए, बस यह जांचें कि संपत्ति ऑब्जेक्ट से संबंधित है या नहीं:

for (i in obj) {
    if (obj.hasOwnProperty(i)) {
        //do stuff
    }
}

साथ ही, ईसीएमएस्क्रिप्ट 5 एक जोड़ा है forEach करने के लिए विधि Array.prototypeजिसका उपयोग कैलबैक का उपयोग करके सरणी पर गणना करने के लिए किया जा सकता है (पॉलीफिल दस्तावेज़ों में है ताकि आप इसे पुराने ब्राउज़रों के लिए अभी भी उपयोग कर सकें):

arr.forEach(function (val, index, theArray) {
    //do stuff
});

यह ध्यान रखना महत्वपूर्ण है Array.prototype.forEach कॉलबैक लौटने पर तोड़ नहीं आता है falsejQuery तथा Underscore.js अपनी खुद की विविधताएं प्रदान करें each लूप प्रदान करने के लिए जो संक्षिप्त सर्किट हो सकता है।


71
2018-02-17 14:00



तो एक ईसीएमएस्क्रिप्ट 5 फोरैच लूप से कैसे टूट जाता है जैसे कि हम लूप के लिए सामान्य या सी-स्टाइल भाषा में पाए जाने वाले फ़ोरैच लूप के लिए सामान्य होंगे? - Ciaran Gallagher
@CiaranG, जावास्क्रिप्ट में देखना आम है each अनुमति देने वाली विधियों return false लूप से बाहर तोड़ने के लिए इस्तेमाल किया जाएगा, लेकिन साथ forEach यह एक विकल्प नहीं है। एक बाहरी ध्वज का उपयोग किया जा सकता है (यानी if (flag) return;, लेकिन यह केवल शेष कार्य निकाय को निष्पादित करने से रोक देगा, forEach अभी भी पूरे संग्रह पर फिर से जारी रहेगा। - zzzzBov


यदि आप किसी सरणी पर लूप करना चाहते हैं, तो मानक तीन-भाग का उपयोग करें for पाश।

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

आप कैशिंग द्वारा कुछ प्रदर्शन अनुकूलन प्राप्त कर सकते हैं myArray.length या पीछे की ओर फिर से।


30
2018-02-17 13:55



के लिए (var i = 0, लंबाई = myArray.length; i <length; i ++) इसे करना चाहिए - Edson Medina
@EdsonMedina यह भी एक नया वैश्विक चर बना देगा length। ;) - joeytwiddle
@joeytwiddle हां, लेकिन यह इस पोस्ट के दायरे से बाहर है। वैसे भी आप एक वैश्विक चर बना देंगे। - Edson Medina
@EdsonMedina मेरी माफ़ी, मैं पूरी तरह से गलत था। का उपयोग करते हुए , एक असाइनमेंट के बाद नहीं एक नया वैश्विक परिचय, तो आपका सुझाव बस है ठीक! मैं इसे एक अलग समस्या के लिए भ्रमित कर रहा था: उपयोग करना = एक असाइनमेंट के बाद बनाता है एक नया वैश्विक - joeytwiddle
वेरिएबल से सावधान रहें नहीं लूप के लिए स्थानीय। जावास्क्रिप्ट में ब्लॉक स्कोप नहीं है। घोषित करना शायद बेहतर है var i, length, arrayItem; इस गलतफहमी से बचने के लिए लूप से पहले। - James


प्रत्येक के लिए कार्यान्वयन (jsFiddle में देखें):

function forEach(list,callback) {
  var length = list.length;
  for (var n = 0; n < length; n++) {
    callback.call(list[n]);
  }
}

var myArray = ['hello','world'];

forEach(
  myArray,
  function(){
    alert(this); // do something
  }
);

25
2018-04-10 00:26



इसमें इटेटरेटर, एक अनावश्यक लंबाई गणना कर रहा है। एक आदर्श मामले में, सूची की लंबाई केवल एक बार गणना की जानी चाहिए। - MIdhun Krishna
@MIdhunकृष्ण मैंने अपना जवाब और जेएसफ़िल्ड अपडेट किया लेकिन जागरूक रहें कि यह उतना आसान नहीं है जितना आप सोचते हैं। इसे देखो सवाल - nmoliveira
पूर्ण और सही कार्यान्वयन यहां पाया जा सकता है: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - marciowb


यदि आपको सरणी खाली करने पर कोई फर्क नहीं पड़ता है:

var x;

while(x = y.pop()){ 

    alert(x); //do something 

}

x का अंतिम मूल्य होगा y और इसे सरणी से हटा दिया जाएगा। आप भी उपयोग कर सकते हैं shift() जो पहले आइटम को देगा और हटा देगा y


25
2018-03-10 02:37



यदि आपके पास एक स्पैस सरणी है तो यह काम नहीं करता है [1, 2, undefined, 3]। - M. Grzywaczewski
... या वास्तव में कुछ भी गलत: [1, 2, 0, 3] या [true, true, false, true] - joeytwiddle