2013-05-31 4 views
8

के इस रेगेक्स फ़िल्टरिंग को समझा सकता है, मैं एक सरणी फ़िल्टर कर रहा हूं, और यहां पर एक रेगेक्स मिला है। मैं इस को समझने के लिए कोशिश कर रहा हूँ:क्या कोई इस सरणी

filterArray.filter(/./.test.bind(new RegExp(key, 'g'))) 

लेकिन मुझे समझ नहीं आता कैसे सरणी परीक्षण यह regex के खिलाफ मूल्य या के साथ शुरू करने के लिए कारण है /./ के बजाय सिर्फ regex लेखन। और इस मामले में कैसे काम करते हैं?

संपादित करें: कुंजी केवल एक स्ट्रिंग है जिसे मैं मिलान करना चाहता हूं, "हाय" या "कुत्ता" या "वास्तव में कुछ भी"।

+2

आप हमें चर 'key' तो देना यदि हाँ। –

+0

@DavidStarkey कृपया मेरा संपादन देखें। – ptf

+0

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind –

उत्तर

14

.bind() विधि this के मान के रूप में पहले तर्क के रूप में पारित किए गए किसी भी कार्य के साथ एक फ़ंक्शन वापस कर देगा।

जब से तुम .test() से .bind() कॉल कर रहे हैं, तो आप new RegExp(key, 'g') करने के लिए बाध्य this साथ .test() विधि हो रही है।

/./ यहां अप्रासंगिक है। यह RegExp.prototype.test विधि प्राप्त करने का एक छोटा सा तरीका है।

नतीजा यह है कि आप को प्रभावी ढंग से करने जा रहे हैं है:

var regexp = new RegExp(key, 'g'); 

filterArray.filter(function(val) { 
    return regexp.test(val); 
}); 

आप ध्यान देना चाहिए कि यह एक छोटा सा खतरनाक है, क्योंकि g संशोधक के साथ एक regex वस्तु स्टेटफुल है। इसका मतलब है कि यह हमेशा एक नई खोज शुरू करता है जहां पिछला एक छोड़ा गया था।

इस फ़िल्टरिंग परिदृश्य को देखते हुए, g बिल्कुल आवश्यक नहीं लगता है, और वास्तव में केवल समस्याएं पैदा कर सकता है।

यहाँ यहाँ g का उपयोग कर के खतरे का एक उदाहरण है:

var re = /./.test.bind(new RegExp("foo", 'g')); 
var str = "foobar"; 

console.log(re(str)); // true 
console.log(re(str)); // false 

तो एक ही स्ट्रिंग पर एक ही regex बुला पैदा करता है दो अलग-अलग परिणाम है। अगर हम इसे फिर से बुलाते हैं, तो यह एक बार फिर true होगा।


तो एक .filter() कॉलबैक के रूप में उपयोग को देखते हुए, मान लें कि key"foo" है करते हैं, तो कहते हैं कि एक val"foobar" है की सुविधा देता है। फिल्टर के माध्यम से इसकी अनुमति होगी।

लेकिन मान लें कि अगले val"foobaz" है। खोज पहले से शुरू करने के बजाय चौथे चरित्र पर फिर से शुरू होगी, इसलिए "foo" नहीं मिलेगा।


यहाँ ठोस उदाहरण है कि कार्रवाई में इस मुद्दे को पता चलता है:

डेमो:http://jsfiddle.net/s9PzL/

var filterArray = [ 
    "foobar", 
    "foobaz", 
    "foobuz", 
    "foobix" 
]; 

var result = filterArray.filter(/./.test.bind(new RegExp("foo", 'g'))); 

सभी श्रृंखलाएं "foo" है, ताकि उन सभी के माध्यम से मिलना चाहिए। लेकिन परिणाम दिखाता है कि ऐसा नहीं होता है।

document.body.textContent = result.join(", "); // foobar, foobuz 
+0

इसे वैश्विक बनाने के बारे में सिर के लिए धन्यवाद। और जिसके परिणामस्वरूप मैं प्रभावी ढंग से काम कर रहा हूं उसका परिणाम। – ptf

+0

आपका स्वागत है। –

+0

जब आप कहते हैं कि 4 वें चार पर खोज फिर से शुरू होती है, तो आप सरणी में अगले तत्व का चौथा चार का मतलब है, है ना? – ptf

6

मुझे लगता है कि ऐसा इसलिए किया जाता है क्योंकि आप सरणी में प्रत्येक आइटम पर परीक्षण विधि निष्पादित करना चाहते हैं। फ़िल्टर करने के लिए टेस्ट विधि को पास करना होगा (संभवतः) विधि के बाध्यकारी को गड़बड़ कर देगा।

इसलिए अपने उदाहरण में:

/./ 

कि regex

/./.test.bind(new Regex(..)) 

बांधता पर एक खाली regex

/./.test 

परीक्षा पद्धति है उत्पन्न करता है कि अनुरोध किया विधि के लिए विधि, और एक नई विधि देता है जो test निष्पादित करता है जहां this आपकी आपूर्ति रेगेक्स key पर आधारित है।

ऐसा लगता है कि यह एक बहुत अधिक स्पष्ट लिखा गया हो सकता:

RegExp.prototype.test.bind(new RegExp(key, 'g')) 
+0

मैं केवल अनुमान लगा सकता हूं कि लेखक 13 और वर्ण टाइप करने के लिए बहुत चालाक है। – deerchao

+0

दरअसल वह है :) –

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