2014-10-18 5 views
6

(मान लीजिए कि यह करने के लिए एक अच्छा कारण है। यदि आप अच्छे कारण को पढ़ना चाहते हैं तो प्रश्न का अंत देखें ।)किसी भी for..in लूप के बिना एक ही परिणाम प्राप्त करें ..in लूप

मैं for in लूप के समान परिणाम प्राप्त करना चाहता हूं, लेकिन बिना उस भाषा निर्माण का उपयोग कर प्राप्त करना चाहता हूं। नतीजतन मेरा मतलब केवल संपत्ति के नामों की एक सरणी है (मुझे उस व्यवहार को पुन: उत्पन्न करने की आवश्यकता नहीं है जो तब होगा जब मैं ऑब्जेक्ट को संशोधित करते समय ऑब्जेक्ट को संशोधित करता हूं)।

कोड में सवाल में कहें, मैं for in के बिना इस समारोह को लागू करना चाहते हैं:

function getPropertiesOf(obj) { 
    var props = []; 
    for (var prop in obj) 
    props.push(prop); 
    return props; 
} 

the for in statement और the Object.keys method के बारे में ECMAScript 5.1 विनिर्देश की मेरी समझ से ऐसा प्रतीत होता निम्नलिखित क्रियान्वयन सही होना चाहिए :

function getPropertiesOf(obj) { 
    var props = []; 
    var alreadySeen = {}; 

    // Handle primitive types 
    if (obj === null || obj === undefined) 
    return props; 
    obj = Object(obj); 

    // For each object in the prototype chain: 
    while (obj !== null) { 
    // Add own enumerable properties that have not been seen yet 
    var enumProps = Object.keys(obj); 
    for (var i = 0; i < enumProps.length; i++) { 
     var prop = enumProps[i]; 
     if (!alreadySeen[prop]) 
     props.push(prop); 
    } 

    // Add all own properties (including non-enumerable ones) 
    // in the alreadySeen set. 
    var allProps = Object.getOwnPropertyNames(obj); 
    for (var i = 0; i < allProps.length; i++) 
     alreadySeen[allProps[i]] = true; 

    // Continue with the object's prototype 
    obj = Object.getPrototypeOf(obj); 
    } 

    return props; 
} 

विचार स्पष्ट रूप से प्रोटोटाइप श्रृंखला चलना, और Object.keys का उपयोग श्रृंखला के प्रत्येक वस्तु में खुद गुण प्राप्त करने के लिए है। हम श्रृंखला में पिछली वस्तुओं में पहले से देखी गई संपत्ति के नामों को बहिष्कृत करते हैं, जिनमें उन्हें गैर-गणना के रूप में देखा गया था। इस विधि भी सम्मान करना चाहिए the additional guarantee mentioned on MDN:

Object.keys() विधि एक दिए गए वस्तु की अपनी गणनीय गुण की एक सरणी, रिटर्न एक for...in पाश द्वारा प्रदान की किसी एक ही क्रम में [...]।

(जोर मेरा है)

मैं इस कार्यान्वयन के साथ एक सा खेला जाता है, और मैं इसे तोड़ने के लिए नहीं कर पाए हैं।

तो सवाल:

अपने विश्लेषण सही है? या क्या मैं इस स्पेस का विस्तार देख रहा हूं जो इस कार्यान्वयन को गलत बना देगा?

क्या आप ऐसा करने का एक और तरीका जानते हैं, जो कार्यान्वयन के सभी मामलों में for in के विशिष्ट क्रम से मेल खाता है?

टिप्पणी:

  • मैं ECMAScript < 5.1 के बारे में परवाह नहीं है।
  • मुझे प्रदर्शन के बारे में परवाह नहीं है (यह विनाशकारी हो सकता है)।

संपादित करें: @ lexicore की जिज्ञासा (लेकिन वास्तव में सवाल का भाग नहीं है) को पूरा करने के, अच्छे कारण के इस प्रकार है। मैं जावास्क्रिप्ट (स्कैला से) के लिए एक कंपाइलर विकसित करता हूं, और for in भाषा निर्माण उन चीजों का हिस्सा नहीं है जो मैं सीधे अपने कंपाइलर के मध्यवर्ती प्रतिनिधित्व में समर्थन करना चाहता हूं। इसके बजाए, मेरे पास "अंतर्निर्मित" फ़ंक्शन getPropertiesOf है जो मूल रूप से मैं पहले उदाहरण के रूप में दिखाता हूं। मैं "उपयोगकर्ता-स्थान" कार्यान्वयन (स्कैला में लिखे गए) द्वारा उन्हें बदलकर जितना संभव हो सके उतने बिल्टिन से छुटकारा पाने की कोशिश कर रहा हूं।प्रदर्शन के लिए, मेरे पास अभी भी एक अनुकूलक है जो कभी-कभी कुछ तरीकों को "अंतर्निहित" करता है, और इस मामले में यह प्रभावी पहले कार्यान्वयन के साथ getPropertiesOf को घुमाएगा। लेकिन इंटरमीडिएट प्रतिनिधित्व ध्वनि बनाने के लिए, और जब अनुकूलक अक्षम हो जाता है, तो मुझे सुविधा के वास्तविक कार्यान्वयन की आवश्यकता होती है, चाहे प्रदर्शन लागत चाहे, जब तक यह सही हो। और इस मामले में मैं for in का उपयोग नहीं कर सकता, क्योंकि मेरा आईआर उस निर्माण का प्रतिनिधित्व नहीं कर सकता है (लेकिन मैं किसी भी ऑब्जेक्ट पर मनमानी जावास्क्रिप्ट फ़ंक्शंस को कॉल कर सकता हूं, उदाहरण के लिए, Object.keys)।

+0

'(obj === null || obj === अपरिभाषित)' 'obj == null' जैसा ही है। जिज्ञासा से, क्या कोई कारण है कि आप अधिक वर्बोज़ फॉर्म का उपयोग कर रहे हैं? – gilly3

+0

@ gilly3 क्योंकि '==' बुरा है। कम राय वाले उत्तर के लिए: इसी कारण से मैं 'इन के लिए 'उपयोग नहीं कर सकता: आईआर जानबूझकर' == '(क्योंकि यह बुरा है ...) का समर्थन नहीं करता है। – sjrd

+0

दिलचस्प। मुझे लगता है कि '==' वास्तव में भाषा की एक * ताकत * है जिसे समझदारी से इस्तेमाल किया जाना चाहिए। – gilly3

उत्तर

3
देखने के विनिर्देश बिंदु से

, केवल इस धारणा के तहत सही अपने विश्लेषण है कि एक विशेष कार्यान्वयन के लिए गणन की एक विशेष क्रम को परिभाषित करता है के लिए में बयान: एक कार्यान्वयन के लिए गणन की एक विशेष क्रम को परिभाषित करता है

हैं फॉर-इन कथन, उसी एल्गोरिदम के चरण 5 में उसी गणना आदेश का उपयोग किया जाना चाहिए।

अंतिम वाक्य here देखें।

तो यदि कार्यान्वयन ऐसा विशिष्ट आदेश प्रदान नहीं करता है, तो फॉर-इन और Object.keys अलग-अलग चीजें वापस कर सकता है। खैर, इस मामले में भी दो अलग-अलग फोर्स अलग-अलग चीजें लौटा सकते हैं।

काफी रोचक, पूरी कहानी प्रश्न को कम कर देती है यदि दो फोर्स-इन्स एक ही परिणाम देगा यदि ऑब्जेक्ट नहीं बदला गया था। क्योंकि, यदि यह मामला नहीं है, तो फिर भी आप "वही" का परीक्षण कैसे कर सकते हैं?

प्रैक्टिस में, यह संभवतः सच होगा, लेकिन मैं आसानी से कल्पना कर सकता हूं कि ऑब्जेक्ट कॉल-इन कॉल के बीच गतिशील रूप से अपनी आंतरिक संरचना का पुनर्निर्माण कर सकता है। उदाहरण के लिए, यदि कुछ संपत्ति का उपयोग अक्सर किया जाता है, तो कार्यान्वयन हैश तालिका को पुन: व्यवस्थित कर सकता है ताकि उस संपत्ति तक पहुंच अधिक कुशल हो। जहां तक ​​मैं देख सकता हूं, विनिर्देश उस पर प्रतिबंध नहीं लगाता है। और यह भी अयोग्य नहीं है।

तो आपके प्रश्न का उत्तर यह है: नहीं, विनिर्देश के अनुसार कोई गारंटी नहीं है, लेकिन फिर भी शायद अभ्यास में काम करेगा।

अद्यतन

मुझे लगता है कि वहाँ एक और समस्या है। यह कहां परिभाषित किया गया है, प्रोटोटाइप श्रृंखला के सदस्यों के बीच गुणों का क्रम क्या है? आपको सही क्रम में "स्वयं" गुण मिल सकते हैं, लेकिन क्या वे इसे ठीक तरह से विलय कर रहे हैं? उदाहरण के लिए, बच्चे के गुण पहले और माता-पिता का अगला क्यों?

+0

ठीक है, मैं समझता हूं।लेकिन अगर अंतर्निहित कार्यान्वयन * एक विशिष्ट आदेश को परिभाषित नहीं करता है, तो मेरा कार्य भी spec को संतुष्ट करता है, है ना? चूंकि आदेश के संदर्भ में संतुष्ट करने के लिए कुछ भी नहीं है, इसलिए मेरे द्वारा उपयोग किए जाने वाले सटीक किसी भी आदेश में ठीक है; आवश्यकता मूल रूप से शून्य है। – sjrd

+0

@sjrd आप सही हैं, अन्यथा साबित करने का कोई तरीका नहीं है। कौन सी आवश्यकता शून्य है, बिल्कुल? – lexicore

+2

आवश्यकता क्या 'in' के लिए क्या करना होगा के रूप में एक ही क्रम में नाम वापस जाने के लिए। यदि अंतर्निहित कार्यान्वयन किसी भी प्रकार के आदेश की गारंटी नहीं देता है, तो यह आवश्यकता शून्य है। – sjrd

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