2014-10-22 8 views
6

मैं Select2 (source code) के माध्यम से देख और each2 विधि प्रोटोटाइप मिला था:चयन 2 प्रत्येक 2 विधि - यह कैसे काम करता है?

$.extend($.fn, { 
    each2 : function (c) { 
    var j = $([0]), i = -1, l = this.length; 
    while (
     ++i < l 
     && (j.context = j[0] = this[i]) 
     && c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object 
    ); 
    return this; 
    } 
}); 

मेरा प्रश्न है - कैसे इस विधि काम करता है? मेरा मतलब है - बयान के बिना केवल स्थिति के बिना लूप क्यों है? मैं वास्तव में इस विधि के प्रवाह को समझना पसंद करूंगा।

+0

क्या आपको उत्तर की समीक्षा करने का मौका मिला था? एक टिप्पणी छोड़ दो क्योंकि यह एक लाइन समाधान नहीं है और यदि यह स्पष्ट नहीं है तो उसे स्पष्टीकरण की आवश्यकता है। –

उत्तर

4

जब आप एक शर्त के अंदर एक अभिव्यक्ति डाल (उदाहरण के लिए: if (i), if (i == null), if (++i), if (i < 2))) अभिव्यक्ति से पहले अपनी 'जाँच' यह true या false है का मूल्यांकन किया जाता है।

लाइव उदाहरण:

हम var i = 0 है; अब आप if (++i) console.log(i) पर कॉल करें। अभिव्यक्ति लौट ++i1 तो console.log(i) लॉग 1 (यह जावास्क्रिप्ट में सच्चाई [ नहीं है] के रूप में समझा जाता है)।

अब मान लें कि हमारे पास var i = 0 और if (++i && ++i) console.log(i) है। पहली अभिव्यक्ति 1 लौटाती है, इसलिए दूसरा भी कहा जाता है जो 2 देता है। दोनों 1 और 2सत्य के रूप में इलाज कर रहे हैं तो console.log(i) लॉग 2

बहुत बढ़िया। चलिए ऊपर जैसा ही उदाहरण देखते हैं लेकिन if से पहले हम var i = -1 प्रारंभ करते हैं। अब हम if (++i && ++i) console.log(i) पर कॉल करते हैं। पहला ++i0 देता है जो झूठी है।

जारी रखने के लिए आपको && काम करना होगा। मुझे जल्दी से समझाता हूँ: आप ढेर तो exp1 && exp2 && exp3 ... && expX तो exp2 केवल निष्पादित किया जाएगा (का मूल्यांकन) जब exp1 रिटर्न सच्चाई (उदाहरण के लिए: true, 1, "some string")। exp3 निष्पादित किया जाएगा केवल अगर exp2truthy, है exp4 जब exp3 सच्चाई और इतने पर ... (जब तक हम expN हिट)

की पीठ f (++i && ++i) console.log(i) को अब चलते हैं है। तो सबसे पहले ++i रिटर्न 0 जो है असत्यता तो दूसरा ++i मार डाला और पूरे conditionfalse तो console.log(i) निष्पादित नहीं किया जाएगा (कैसे कभी incrementation पूरा कर लिया गया तो i अब 0 के बराबर) है नहीं है।

अब जब आप इसे प्राप्त करते हैं तो मैं आपको बता सकता हूं कि while लूप condition चेकिंग तरीके से समान कार्य करता है। उदाहरण के लिए var = -2 और while (++i)++i रिटर्न झूठी (0) तक निष्पादित किया जाएगा। while (++1) बिल्कुल 2 बार निष्पादित किया जाएगा।

टीएल; डीआर नीचे !!!

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

while (
     ++i < l 
     && (j.context = j[0] = this[i]) 
     && c.call(j[0], i, j) !== false 
    ); 

मुझे लगता है कि समझाने के लिए सबसे अच्छा तरीका यह पुनर्लेखन के लिए है (:

while (++i < l) { 
     if (!(j.context = j[0] = this[i])) break; 
     if (!(c.call(j[0], i, j) !== false)) break; 
    } 

या कभी कम जादुई:

var i = 0; 
    while (i < l) { 
     if (!(j.context = j[0] = this[i])) break; 
     if (!(c.call(j[0], i, j) !== false)) break; 
     i++; 
    } 
+0

लेकिन लूप के उपरोक्त उदाहरण में वास्तव में क्या निष्पादित किया जाएगा? कोई बयान नहीं, केवल हालत। यह वह हिस्सा है जिसमें मुझे समस्या है। मान लें कि मेरे लूप को 2 बार निष्पादित किया गया है - कौन सा हिस्सा निष्पादित किया गया है? –

+0

है। मेरा मानना ​​है कि '(j.context = j [0] = यह [i]) 'इस एल्गोरिदम का मूल है। इसके अलावा 'c.call (j [0], i, j) 'यहां' चीज़ 'कर सकता है। –

+0

क्या आप वाकई इस तरह इसे फिर से लिख सकते हैं? क्या आप इस तरह के परिवर्तन के लिए किसी प्रकार का स्रोत प्रदान कर सकते हैं? –

3

कोड का उद्देश्य है एक नया कार्य जोड़ने के लिए each2 jQuery ऑब्जेक्ट में जो .each के समान काम करता है। इस .each2 फ़ंक्शन का उपयोग .each जैसा है जो एक jQuery objec पर निष्पादित करता है टी, 2 तर्क (अनुक्रमणिका और मूल्य) के साथ वापस कॉल करने के लिए एक फ़ंक्शन लेता है और jQuery ऑब्जेक्ट देता है।

रहस्यमय जबकि पाश,

while (
    ++i < l 
    && (j.context = j[0] = this[i]) 
    && c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object 
); 
    return this; 
} 

टिप्पणियों:

  1. जारी सभी 3 की स्थिति true
  2. पहले स्थिति का मूल्यांकन "केवल तभी": ++i < l, एक सरल पुनरावृति का मूल्यांकन सत्य जब तक i के मान चयनित तत्वों की गणना से कम नहीं है।
  3. दूसरा स्थिति [i अगली पंक्ति में ++i और i के उपयोग की वजह से, -1 को आरंभ नहीं हो जाता बाद में संदर्भ में सूचकांक के रूप में प्रयोग किया जाता है]: यह वास्तव में एक प्रारंभ + अशक्त/अपरिभाषित जांच है। सभी वैध मानों के लिए स्थिति का मूल्यांकन सही है और जब कोई अमान्य संदर्भ होता है तो विफल रहता है।
  4. तीसरी हालत: यदि कॉल बैक फ़ंक्शन झूठी वापसी करता है तो इस स्थिति का उद्देश्य आपको लूप से बाहर निकलने की अनुमति देता है। .each के समान है जहां फ़ंक्शन के अंदर return false पुनरावृत्ति को तोड़ देगा।
+0

आप दो चीजों को छोड़कर सही हैं। 'प्रत्येक 2' सरणी पर काम करता है (या लंबाई के साथ कुछ भी जिसे पुनरावृत्त किया जा सकता है। और आपका पहला अवलोकन गलत है, यह तब जारी रहता है जब * सभी 3 स्थितियां सत्य हों। – RustyToms

+0

@RustyToms धन्यवाद, लेकिन jQuery ऑब्जेक्ट की लंबाई है और यह हालांकि, मैं यह नहीं कहूंगा कि '.each2' इसका अर्थ है। '.ach2' विशेष रूप से उस प्लगइन के लिए बनाया गया है, इसलिए उपयोग केवल उपयोगिता समारोह के रूप में काम करने तक ही सीमित हो सकता है। और मेरा पहला अवलोकन बस बताता है यह तब तक जारी रहता है जब तक कि कोई भी स्थिति झूठी मूल्यांकन न करे, सुनिश्चित न करें कि उस संदर्भ में "कब तक" और "केवल अगर" अलग है। –

+0

मेरा मतलब था कि 'प्रत्येक 2' jQuery ऑब्जेक्ट्स तक सीमित नहीं था, लेकिन हाँ, मुझे लगता है क्योंकि 'प्रत्येक 2' '$' (jQuery ऑब्जेक्ट) को बढ़ाता है, आप सही हैं, यह jQuery ऑब्जेक्ट विशिष्ट है। मुझे लगता है कि आप अपने पहले अवलोकन के बारे में भी सोच रहे हैं, लेकिन आपका व्याकरण गलत है। "जब तक" और "केवल अगर" विपरीत हैं। जब आप कहते हैं "सभी 3 conditio तक जारी है एनएस सच साबित करता है "आप कह रहे हैं कि यदि सभी 3 स्थितियों का सत्य मूल्यांकन होता है तो यह तुरंत बंद हो जाएगा। लेकिन विपरीत सच है, यह केवल तब तक जारी रहेगा जब तक कि सभी 3 सत्य हैं। तो बस "अगर" के साथ "जब तक" को प्रतिस्थापित करें, तो आपका उत्तर सही है। – RustyToms

1

ओपी द्वारा नोट किया गया है, while स्थिति के बाद कोई विवरण नहीं है। थोड़ी देर के बाद अर्धविराम नोट करें, return this केवल लूप पूरा होने के बाद ही चलाया जाता है, और यह तब होता है जब तीन में से कोई भी कथन गलत साबित होता है। यदि आप सभी जानना चाहते हैं कि टाइम लूप कैसे काम कर रहा है, तो फिलिप बार्टुजी का जवाब शायद सबसे पूरा है। मैं each2 विधि के अनुसार एक व्यापक उत्तर देने का प्रयास करूंगा।

के रूप में किए गए दस्तावेज़ों में बताया गया है, यह सिर्फ jQuery's #each, या Array.prototype.forEach या Underscore's #each या lodash's #forEach कि Select2 के उपयोग के लिए विशेष रूप से डिजाइन किया गया है के लिए एक अधिक कुशल संस्करण है। इसका उपयोग किसी भी ऑब्जेक्ट या अन्य पुनरावर्तनीय पर एक jQuery ऑब्जेक्ट में लपेटने के लिए किया जाता है। तो यह स्ट्रिंग्स के साथ-साथ jQuery संग्रह के सरणी के लिए भी प्रयोग किया जाता है।

जिस तरह से यह काम करता है वह दायरा है (this) वह सरणी है जिसे इसे कॉल किया गया था। इसे एक तर्क के रूप में एक समारोह दिया जाता है। यह ठीक है कि मैंने पहले उल्लेख किए गए अन्य each विधियों को कैसे कहा जाता है। each2 को प्रदान किया गया फ़ंक्शन सरणी में प्रत्येक आइटम के लिए एक बार कहा जाता है। जबकि लूप सरणी में प्रत्येक आइटम पर पुनरावृत्ति करने के लिए एक हैकी तरीका है, और फ़ंक्शन को कॉल करें, आइटम को संदर्भ के रूप में सेट करें और सरणी में अनुक्रमणिका को पास करें और आइटम को jQuery ऑब्जेक्ट के रूप में पहले और दूसरे तर्क के रूप में पास करें।while लूप स्थिति में प्रत्येक कथन का मूल्यांकन यह निर्धारित करने के लिए किया जाना चाहिए कि यह सत्य है या नहीं, और यह प्रक्रिया वास्तव में चरों को मान असाइन करने और i बढ़ाने के लिए उपयोग की जा रही है। c.call(j[0], i, j) !== false भाग फ़ंक्शन को झूठी लौटकर प्रारंभिक रूप से लूप को समाप्त करने की अनुमति देता है। यदि फ़ंक्शन गलत लौटाता है, तो जबकि लूप रुक जाएगा, अन्यथा यह il से अधिक होने तक जारी रहेगा, जिसका अर्थ है कि सरणी में प्रत्येक आइटम का उपयोग किया गया है। लौटने के बाद .each2 के बाद सरणी में एक और विधि को जंजीर करने के लिए सक्षम बनाता है।

मूल रूप से while पाश करने के लिए फिर से लिखा जा सकता है:

var j = $([0]), i = 0, l = this.length, continue = true; 
while (i < l) { 
    i++; 
    j.context = j[0] = this[i]; 
    continue = c.call(j[0], i, j); 
    if (!continue) { 
    break; 
    } 
} 

लेकिन वहाँ शायद कुछ प्रदर्शन कारण है कि ब्राउज़र द्वारा रूप में अच्छी तरह से अनुकूलित नहीं किया जा सकता है।

यह सामान्य each विधियों की तुलना में अधिक नाजुक है। उदाहरण के लिए यदि सरणी में एक तत्व का झूठा मान है जैसे कि 0, (j.context = j[0] = this[i]) गलत होगा, जिससे लूप समाप्त हो जाएगा। लेकिन इसका उपयोग केवल चयन 2 कोड के विशेष मामलों में किया जाता है, जहां ऐसा नहीं होना चाहिए।

चलो कुछ उदाहरणों के माध्यम से चलते हैं।

function syncCssClasses(dest, src, adapter) { 
    var classes, replacements = [], adapted; 

    classes = $.trim(dest.attr("class")); 

    if (classes) { 
     classes = '' + classes; // for IE which returns object 

     $(classes.split(/\s+/)).each2(function() { 
      if (this.indexOf("select2-") === 0) { 
       replacements.push(this); 
      } 
     }); 
    } 
    ... 

^यह कोड एक dest DOM एलीमेंट से कक्षाएं हो रही है। कक्षाओं को तारों की एक सरणी में विभाजित किया जाता है (स्ट्रिंग को व्हाइटस्पेस वर्णों पर विभाजित किया जा रहा है, यह \s+ नियमित अभिव्यक्ति है), प्रत्येक वर्ग का नाम सरणी में एक आइटम है। यहां कोई विशेष jQuery काम की आवश्यकता नहीं है, इसलिए 2 तर्क जो each2 द्वारा बुलाए गए फ़ंक्शन का उपयोग नहीं किया जाता है। यदि वर्ग 'select2-' से शुरू होता है तो कक्षा को replacements नामक सरणी में जोड़ा जाता है। 'चयन 2-' वर्गों की प्रतिलिपि बनाई जा रही है, बहुत सरल।

group.children=[]; 
$(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); }); 

^संक्षिप्तता के लिए मैं इस विधि के बाकी शामिल नहीं किया है, लेकिन यह process विधि का हिस्सा है। इस मामले में, each2 का उपयोग process एक नोड और उसके सभी बच्चों के लिए किया जा रहा है। $(datum.children) एक jQuery चयन है, प्रत्येक 'बच्चा' (नाम childDatum) बदले में संसाधित किया जाएगा, और यह बच्चे एक ही प्रक्रिया के माध्यम से चले जाएंगे। group.children सरणी को संग्रह के रूप में उपयोग किया जाएगा, जो प्रत्येक childDatum के लिए उस सरणी में जो भी जोड़ा जाता है, उपलब्ध होगा, इसलिए each2 चलाए जाने के बाद यह सभी बच्चों, पोते, आदि के प्रसंस्करण के दौरान जो कुछ भी जोड़ा गया है, उसे रखेगा

संबंधित मुद्दे