2014-06-12 7 views
8

इस MDN पृष्ठ पर [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find] इस polyfill है:क्या कोई इस Array.prototype.find() polyfill को समझा सकता है?

if (!Array.prototype.find) { 
    Object.defineProperty(Array.prototype, 'find', { 
    enumerable: false, 
    configurable: true, 
    writable: true, 
    value: function(predicate) { 
     if (this == null) { 
     throw new TypeError('Array.prototype.find called on null or undefined'); 
     } 
     if (typeof predicate !== 'function') { 
     throw new TypeError('predicate must be a function'); 
     } 
     var list = Object(this); 
     var length = list.length >>> 0; 
     var thisArg = arguments[1]; 
     var value; 

     for (var i = 0; i < length; i++) { 
     if (i in list) { 
      value = list[i]; 
      if (predicate.call(thisArg, value, i, list)) { 
      return value; 
      } 
     } 
     } 
     return undefined; 
    } 
    }); 
} 

मेरे सवाल है के लिए इन पंक्तियों क्या कर रहे हैं:

var list = Object(this); 
var length = list.length >>> 0; 

this के बाद निश्चित रूप से एक सरणी (हम Array.prototype बढ़ाने कर रहे हैं) तो क्यों सुनिश्चित करें कि length संख्यात्मक है, और ऑब्जेक्ट() का उपयोग क्यों किया जाता है?

+2

इस polyfill के साथ परेशानी यह है कि ऐसा करना आवश्यक हो तो मैं यह कर सकता है Object.defineProperty विधि, जो पुराने ब्राउज़र में उपलब्ध नहीं है जो खोजने को लागू नहीं करती हैं। – kennebec

+0

जैसा कि उत्तर इंगित किया गया है; 'यह' एक सरणी होने की गारंटी नहीं है, आप निम्न उत्तर में देख सकते हैं कि यह क्या हो सकता है (यदि आपको प्रदान किए गए टीजे से अधिक जानकारी चाहिए): http://stackoverflow.com/a/16063711/1641941 (नीचे 'यह चर ') – HMR

उत्तर

10

मौलिक उत्तर यह है कि पॉलीफिल ईएस 6 ड्राफ्ट स्पेक (§22.1.3.8 मई 22 ड्राफ्ट के रूप में) में एल्गोरिदम के चरण 1 और चरण 4 को ईमानदारी से कार्यान्वित कर रहा है।

1. हे तर्क के रूप में इस मूल्य गुजर ToObject बुला का नतीजा हो करते हैं।

...

4. लेन ToLength (lenValue) बनें।

(कहाँ ToLength मूल रूप से एक नंबर के लिए एक रूपांतरण है।)

और यह Function#call और Function#apply, के माध्यम से या सिर्फ फ़ंक्शन को कॉल सीधे द्वारा this आजकल (के लिए गैर-वस्तु मूल्यों का उपयोग करने के लिए संभव के रूप में सख्त मोड में), चरण 1 समझ में आता है।

this के बाद निश्चित रूप से एक सरणी (हम Array.prototype बढ़ाने कर रहे हैं) तो क्यों यकीन है कि लंबाई संख्यात्मक है, और क्यों Object() प्रयोग किया जाता है बनाने के है?

लेकिन हम नहीं जानते कि कि this एक सरणी है । वर्तमान ईएस 6 ड्राफ्ट स्पेक से यह नोट देखें:

find फ़ंक्शन जानबूझकर सामान्य है; इसकी आवश्यकता नहीं है कि इसकी this मान एक ऐरे ऑब्जेक्ट हो। इसलिए इसे विधि के रूप में उपयोग के लिए अन्य प्रकार की वस्तुओं में स्थानांतरित किया जा सकता है। चाहे find फ़ंक्शन को किसी विदेशी ऑब्जेक्ट पर सफलतापूर्वक लागू किया जा सकता है जो कि ऐरे कार्यान्वयन-निर्भर नहीं है।

आपको प्रोटोटाइप को आवंटित लगभग सभी पूर्वनिर्धारित कार्यों पर यह नोट मिलेगा।

जैसे, आप, या तो उन्हें वस्तुओं या अन्य प्रोटोटाइप के लिए सीधे बताए द्वारा अन्य बातों के लिए उपयोग कर सकते हैं:

MyNiftyThing.prototype.find = Array.prototype.find; 

... या Function#call के माध्यम से या Function#apply

तो मान लीजिए कि मैं arguments ऑब्जेक्ट पर उपयोग करना चाहता था।arguments, ज़ाहिर है, सरणी की तरह लेकिन एक सरणी नहीं है।

function foo() { 
    var firstObject = Array.prototype.find.call(arguments, function(val) { 
     return typeof val === "object"; 
    }); 
    // ... 
} 

एक और अधिक प्रसिद्ध उदाहरण (find को शामिल नहीं) slice उपयोग कर रहा है विन्यास में, सरणी की तरह वस्तुओं कन्वर्ट करने के लिए:

function foo() { 
    // Turn the `arguments` pseudo-array into a real array 
    var args = Array.prototype.slice.call(arguments, 0); 
} 
+0

बहुत अच्छा जवाब के लिए बहुत बहुत धन्यवाद। –

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