अर्रे के "हर", या "कुछ" खराब में दुष्प्रभाव हैं?


9

मुझे हमेशा सिखाया गया है कि किसी ifहालत में साइड-इफ़ेक्ट होना बुरा है। मेरा कहने का तात्पर्य है;

if (conditionThenHandle()) {
    // do effectively nothing
}

... विरोध के रूप में;

if (condition()) {
    handle();
}

... और मैं समझता हूं कि, और मेरे कोलेजियम खुश हैं क्योंकि मैं ऐसा नहीं करता हूं, और हम सभी शुक्रवार को 17:00 बजे घर जाते हैं और सभी को एक मीरा सप्ताहांत होता है।

अब, ECMAScript5 शुरू की तरह के तरीकों every()और some()करने के लिए Array, और मैं उन्हें बहुत उपयोगी पाते हैं। वे क्लीनर से अधिक हैं for (;;;), आपको एक और गुंजाइश देते हैं, और एक चर द्वारा तत्व को सुलभ बनाते हैं।

हालाँकि जब इनपुट को मान्य किया जाता है, तो मैं अधिक-अक्सर-से- इनपुट का सत्यापन करने की स्थिति में स्वयं का उपयोग नहीं करता every/ करती हूं some, फिर इनपुट को एक प्रयोग करने योग्य मॉडल में परिवर्तित करने के लिए शरीर में every/ some फिर से उपयोग करें ;

if (input.every(function (that) {
    return typeof that === "number";
})) {
    input.every(function (that) {
        // Model.findById(that); etc
    }
} else {
    return;
}

... जब मैं जो करना चाहता हूं वह है;

if (!input.every(function (that) {
    var res = typeof that === "number";

    if (res) {
        // Model.findById(that); etc.
    }

    return res;
})) {
    return;
}

... जो मुझे एक if, हालत में दुष्प्रभाव देता है , जो खराब है।

तुलना में, यह एक पुराने के साथ कोड लगेगा for (;;;);

for (var i=0;i<input.length;i++) {
    var curr = input[i];

    if (typeof curr === "number") {
        return;
    }

    // Model.findById(curr); etc.
}

मेरे प्रश्न हैं:

  1. क्या यह निश्चित रूप से एक बुरा अभ्यास है?
  2. क्या मैं (मिस। अब) का उपयोग कर रहा हूं ( someऔर क्या मुझे इसके लिए उपयोग करना चाहिए ?)everyfor(;;;)
  3. क्या एक बेहतर दृष्टिकोण है?

3
प्रत्येक और कुछ के साथ-साथ फ़िल्टर, मानचित्र, और घटाएँ प्रश्न हैं, उनका कोई दुष्प्रभाव नहीं है, यदि वे ऐसा करते हैं तो आप उन्हें गाली दे रहे हैं।
बेंजामिन ग्रुएनबाम

@BenjaminGruenbaum: तो क्या यह उन्हें नहीं की तुलना में अधिक बार टूथलेस बनाता है? 9/10, अगर मैं उपयोग करता हूं, तो मैं तत्व के साथ कुछsome करना चाहता हूं , अगर मैं उपयोग करता हूं, तो मैं उन सभी तत्वों के लिए कुछ करना चाहता हूं ... और मुझे उस जानकारी तक पहुंचने नहीं देता, इसलिए या तो मैं नहीं कर सकता हूं उनका उपयोग करें, या मुझे साइड-इफेक्ट जोड़ना होगा। everysomeevery
इसहाक

नहीं, जब मैं साइड इफेक्ट्स का संदर्भ देता हूं, तो मेरा मतलब शरीर नहीं तो सिर के अंदर। शरीर के अंदर आप इसे अपनी इच्छानुसार संशोधित कर सकते हैं। बस उस कॉलबैक के अंदर ऑब्जेक्ट को म्यूट न करें जिसे आप कुछ / जब पास करते हैं।
बेंजामिन ग्रुएनबाम

@BenjaminGruenbaum: लेकिन यह बिल्कुल मेरी बात है। अगर मैं का उपयोग someमेरी में ifहालत निर्धारित करने के लिए सरणी में एक निश्चित तत्व एक निश्चित संपत्ति, 9/10 मैं काम करने के लिए की जरूरत है कि क्या दर्शाती है पर मेरी में उस तत्व ifशरीर; अब, जैसा someकि मुझे नहीं बताया गया है कि कौन से तत्वों ने संपत्ति का प्रदर्शन किया (बस "एक किया"), मैं या तो शरीर में some फिर से उपयोग कर सकता हूं (ओ (2 एन)), या मैं सिर्फ अगर स्थिति के अंदर ऑपरेशन कर सकता हूं ( जो बुरा है, क्योंकि इसका सिर के भीतर एक दुष्प्रभाव है)।
इसहाक

... वही लागू होता है every, निश्चित रूप से।
इसहाक

जवाबों:


9

अगर मैं आपकी बात को सही तरह से समझ पा रहा हूं, तो आप गलत इस्तेमाल करने या गाली everyदेने लगते हैं और someअगर आप अपने सरणियों के तत्वों को सीधे बदलना चाहते हैं तो यह थोड़ा अनुचित है। अगर मैं गलत हूं तो मुझे सुधारें, लेकिन आप जो करने की कोशिश कर रहे हैं वह यह पता लगा सकता है कि क्या आपके अनुक्रम में कुछ या हर तत्व एक निश्चित स्थिति प्रदर्शित करता है, फिर इन तत्वों को संशोधित करें। इसके अलावा, आपका कोड सभी वस्तुओं पर तब तक कुछ न कुछ लग रहा है जब तक कि आप एक ऐसा नहीं पाते हैं जो विधेय को पारित नहीं करता है और मुझे नहीं लगता है कि आपका क्या मतलब है। वैसे भी।

आइए अपना पहला उदाहरण लें (थोड़ा संशोधित)

if (input.every(function (that) {
    return typeof that === "number";
})) {
    input.every(function (that) {
        that.foo();
    }
} else {
    return;
}

आप यहाँ क्या कर रहे हैं वास्तव में कुछ / हर / नक्शे / कम / फिल्टर / आदि अवधारणाओं की भावना के खिलाफ थोड़ा सा जाता है। Everyइसका मतलब हर वस्तु को प्रभावित करने के लिए इस्तेमाल किया जाना है, जो किसी चीज के अनुरूप है, बल्कि इसका उपयोग केवल आपको यह बताने के लिए किया जाना चाहिए कि क्या संग्रह में प्रत्येक वस्तु है। यदि आप सभी मदों के लिए एक फ़ंक्शन लागू करना चाहते हैं जिसके लिए एक विधेय सच का मूल्यांकन करता है, तो "अच्छा" करने का तरीका

var filtered = array.filter(function(item) {
    return typeof item === "number";
});

var mapped = filtered.map(function(item) {
    return item.foo(); //provided foo() has no side effects and returns a new object of item's type instead.  See note about foreach below.
});

वैकल्पिक रूप से, आप foreachआइटम को इन-प्लेस संशोधित करने के लिए नक्शे के बजाय उपयोग कर सकते हैं ।

someमूल रूप से एक ही तर्क लागू होता है :

  • आप everyपरीक्षण करने के लिए उपयोग करते हैं यदि किसी सरणी में सभी तत्व कुछ परीक्षण पास करते हैं।
  • आप someपरीक्षण करने के लिए उपयोग करते हैं यदि किसी सरणी में कम से कम एक तत्व कुछ परीक्षण पास करता है।
  • आप mapइनपुट ऐरे में प्रत्येक तत्व के लिए 1 तत्व (जो आपकी पसंद के कार्य का परिणाम है) के साथ एक नया सरणी वापस करने के लिए उपयोग करते हैं।
  • आप का उपयोग filterलंबाई 0 <की एक सरणी वापस जाने के लिए length< initial array lengthतत्वों, सभी मूल सरणी में निहित है और सभी आपूर्ति विधेय परीक्षण गुजर।
  • foreachयदि आप नक्शा चाहते हैं, लेकिन जगह में उपयोग करते हैं
  • आप का उपयोग reduceकरता है, तो आप एक ही वस्तु परिणाम (जो एक सरणी हो सकता है लेकिन नहीं है) में एक सरणी के परिणामों को जोड़ करना चाहते हैं।

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

EDIT (टिप्पणियों के प्रकाश में): तो चलिए बताते हैं कि आप इस बात को मान्य करना चाहते हैं कि हर तत्व एक वस्तु है और यदि वे सभी मान्य हैं तो उन्हें एक एप्लिकेशन मॉडल में बदल दें। एक एकल पास में ऐसा करने का एक तरीका होगा:

var dirty = false;
var app_domain_objects = input.map(function(item) {
    if(validate(item)) {
        return new Model(item);
    } else {
        dirty = true; //dirty is captured by the function passed to map, but you know that :)
    }
});
if(dirty) {
    //your validation test failed, do w/e you need to
} else {
    //You can use app_domain_objects
}

इस तरह, जब कोई ऑब्जेक्ट सत्यापन पास नहीं करता है, तो आप अभी भी पूरे एरे के माध्यम से पुनरावृत्ति करते रहते हैं, जो कि केवल सत्यापन करने की तुलना में धीमी होगी every। हालाँकि, अधिकांश समय आपका सरणी मान्य होगा (या मुझे इसकी आशा करनी चाहिए), इसलिए अधिकांश मामलों में आप अपने सरणी पर एक ही पास का प्रदर्शन करेंगे और एप्लिकेशन मॉडल ऑब्जेक्ट के उपयोग योग्य सरणी के साथ समाप्त हो जाएंगे। शब्दार्थ का सम्मान किया जाएगा, साइड-इफेक्ट से बचा जाएगा और हर कोई खुश होगा!

ध्यान दें कि आप अपनी स्वयं की क्वेरी भी लिख सकते हैं, जो कि फॉर्च के समान है, जो किसी ऐरे के सभी सदस्यों के लिए एक फ़ंक्शन लागू करेगी और यदि वे सभी एक विधेय परीक्षण पास करते हैं तो यह सच / गलत होगा। कुछ इस तरह:

function apply_to_every(arr, predicate, func) {
    var passed = true;
    for(var i = 0; i < array.length; ++i) {
        if(predicate(arr[i])) {
            func(arr[i]);
        } else {
            passed = false;
            break;
        }
    }
    return passed;
}

हालांकि यह जगह में सरणी को संशोधित करेगा।

मुझे उम्मीद है कि यह मदद करता है, यह लिखने में बहुत मज़ा आया। चीयर्स!


आपके उत्तर के लिए धन्यवाद। मैं आवश्यक रूप से प्रति-से- जगह तत्वों को संशोधित करने की कोशिश नहीं कर रहा हूं ; अपने वास्तविक कोड में, मैं इतना मैं पहली बार कर रहा हूँ वस्तुओं की JSON- प्रारूपण सरणी प्राप्त कर रहा हूँ, मान्य इनपुट if (input.every()), जांच करने के लिए कि प्रत्येक तत्व है एक वस्तु ( typeof el === "object && el !== null) आदि, तो अगर इस बात को मान्य, मैं में प्रत्येक तत्व परिवर्तित करना चाहते हैं संबंधित आवेदन मॉडल (जो है, अब आप का उल्लेख map()मैं इस्तेमाल कर सकते हैं input.map(function (el) { return new Model(el); });, लेकिन जरूरी नहीं कि जगह में
इसहाक

.. लेकिन यह भी देखिए कि map()मैं दो बार सरणी पर पुनरावृति कर रहा हूं; एक बार मान्य करने के लिए, और दूसरे को रूपांतरित करने के लिए। हालांकि, एक मानक का उपयोग कर for(;;;)पाश, मैं एक यात्रा का उपयोग कर ऐसा कर सकता है, लेकिन मैं लागू करने के लिए एक तरह से नहीं मिल रहा है every, some, mapया filterइस परिदृश्य में, और केवल प्रदर्शन एक पास, अवांछित-साइड इफेक्ट होने या अन्यथा बुरा शुरू करने के बिना अभ्यास करते हैं।
इसहाक

@ आईसैक ठीक है, देरी के लिए खेद है, मैं आपकी स्थिति को अब और अधिक स्पष्ट रूप से समझता हूं। मैं कुछ सामान जोड़ने के लिए अपने उत्तर को संपादित करूँगा।
pwny

शानदार जवाब के लिए धन्यवाद; यह वास्तव में उपयोगी है :)।
इसहाक

-1

साइड इफेक्ट्स अगर हालत में नहीं हैं, तो वे अगर शरीर में हैं। आपने केवल यह निर्धारित किया है कि वास्तविक स्थिति में उस निकाय को निष्पादित करना है या नहीं। यहां आपके दृष्टिकोण में कुछ भी गलत नहीं है।


नमस्कार, आपके जवाब के लिए धन्यवाद। क्षमा करें, लेकिन या तो मैंने आपके उत्तर को गलत समझा है, या आपने कोड की गलत व्याख्या की है ... मेरे कोड स्निपेट में सब कुछ ifशर्त के भीतर है , केवल शरीर के returnअंदर होने के साथ if; जाहिर है मैं कोड नमूने के बारे में बात कर रहा हूं जो "आगे क्या करना चाहता है? ...
इसहाक

1
क्षमा करें, @ इस्साक के दुष्प्रभाव वास्तव में इस ifस्थिति में हैं।
रॉस पैटरसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.