2015-09-04 7 views
5

इनपुट सत्यापन के रूप में मुझे एक बूलियन मान का मूल्यांकन करने के लिए '9>6' जैसे स्ट्रिंग को सह-संयोजित करने की आवश्यकता है।वैकल्पिक ईविल इवल - रिलेशनल ऑपरेटर

स्ट्रिंग का मूल्यांकन करने के अलावा मुझे कोई कामकाज नहीं मिल रहा है।

मैंने हमेशा eval की बुराई के बारे में सुना है (विशेष रूप से जब से मैं एक फॉर्म इनपुट मान्य कर रहा हूं), इस तथ्य के बारे में कि यह किसी भी स्क्रिप्ट और प्रदर्शन के मुद्दों का मूल्यांकन कर सकता है।

लेकिन ....

वहाँ my case (संबंधपरक ऑपरेटर के साथ काम कर) में किसी भी विकल्प हैं?

var arr = ['<9', '>2']; 

var check = function (a) { 

    return arr.every(function (x) { 
      var string = ''; 

      string += a + x; 

      try { 
       return eval(string); 
      } catch (e) { 
       return false; 
      } 
     }); 
    }; 

console.log(check('3')) 
+2

आप एक दुभाषिया पैटर्न का मूल्यांकन कर सकते हैं http://www.dofactory.com/javascript/interpreter-design-pattern – InferOn

+0

या वेबवर्कर का उपयोग करने और वहां eval का उपयोग करने के बारे में, और अपने शेष एप्लिकेशन के संदर्भ से इसका मूल्यांकन कैसे करें – atmd

+0

@atmd यह समस्या स्थानीय स्क्रिप्ट पर आई जिसने फ़ॉर्म इनपुट के माध्यम से मूल्य प्राप्त किए, यह वास्तव में काफी अच्छी तरह से काम करता है (कोई उल्लेखनीय प्रदर्शन समस्या नहीं)। मुझे एक और सरल समाधान नहीं मिल सका और मेरे पास वास्तव में एक विकल्प खोजने का कोई व्यावहारिक कारण नहीं है, लेकिन चूंकि eval की इतनी बुरी प्रतिष्ठा है। । । – maioman

उत्तर

1

मैं तीन बातें सुधार करने के लिए देख सकते हैं:

  • इसके बजाय a मूल्य stringifying और अपने अभिव्यक्ति के लिए यह श्रृंखलाबद्ध की

    , तुम बस सीधे इतना है कि आप के लिए तुलना कर सकते हैं a चर का संदर्भ लेना चाहिए मूल्य का सही रूप। अन्यथा आप अजीब व्यवहार प्राप्त कर सकते हैं।

    return eval("a " + x); 
    
  • के बाद से आप शायद check कई बार उपयोग कर रहे हैं, तो आप (प्रति कॉल या यहाँ तक कि कई बार) eval हर बार नहीं बुलाना चाहिए। आप स्ट्रिंग्स को एक बड़ी && अभिव्यक्ति में लिख सकते हैं, और इससे भी बेहतर आप शर्तों को पहले से ही एक ही फ़ंक्शन में संकलित कर सकते हैं ताकि आपको पर check से कॉल करने की आवश्यकता न हो।

  • आप Function constructoreval के बजाय का उपयोग कर विचार करना चाहिए।

उन के साथ

आपका कोड कुछ इस प्रकार दिखाई देंगे:

var arr = ['<9', '>2']; 

var check = new Function("a", "return "+arr.map(function(x) { 
    return "a"+x; 
}).join(" && ")+";"); 
console.log(check.toString()); // function anonymous(a) { return a<9 && a>2; } 
console.log(check('3')); 

या इस:

var arr = ['<9', '>2']; 
var fns = arr.map(function(x) { 
    return new Function("a", "return a "+x+";"); 
}); 
function check(a) { 
    return fns.every(function(f) { 
     return f(a); 
    }); 
} 
console.log(check('3')); 
बेशक

मैं उम्मीद कर रहा हूँ कि arr उपयोगकर्ता द्वारा नियंत्रित नहीं है (या बुरा , वर्तमान उपयोगकर्ता के अलावा); यदि आप अपने उपयोगकर्ताओं को उन शर्तों को इनपुट करने की अपेक्षा करते हैं तो आपको उन्हें स्पष्ट रूप से श्वेतसूची में डालना सुनिश्चित करना चाहिए, या शायद एक अधिक परिष्कृत अभिव्यक्ति व्याकरण/पार्सर/मूल्यांकनकर्ता का उपयोग कर सकते हैं।
जब तक यह मामला नहीं है, eval (या उस मामले के लिए, Function) बिल्कुल बुरा नहीं है, यह आपके कोड को छोटा (और संभव सरल) करता है। आप पूरी तरह से फंसे हुए कार्यों को लिख सकते थे (जैसे कि नाइट और पीटर ने सुझाव दिया)।

+1

फ़ंक्शन कन्स्ट्रक्टर रनटाइम में तारों को भी व्याख्या करता है, इस प्रकार इसमें सभी eval के नुकसान भी होते हैं। – peterh

+0

@ पीटर: 'फंक्शन' कन्स्ट्रक्टर 'eval' के दायरे के साथ समस्याओं से बचाता है। निस्संदेह यह रनटाइम पर तारों को संकलित करता है, लेकिन यह एक बुरी चीज नहीं है, खासकर यदि केवल मेरे उत्तर में सुझाए गए एक बार किया जाता है। – Bergi

+0

@ पीटर: उन प्रश्नों को भी देखें जिन पर मोग्सदाड टिप्पणियों से जुड़ा हुआ है। असल में, केवल [नुकसान # 2] रहता है (http://stackoverflow.com/a/86580/1048572) - और [कुछ फायदे] (http://stackoverflow.com/a/197823/1048572)। – Bergi

2

एक विकल्प सहायक कार्यों को परिभाषित करना होगा, लेकिन यह दृष्टिकोण कितना उपयोगी होगा कि आप बड़े चित्र में क्या हासिल करना चाहते हैं।

function geq(n) { 
    return function(m) { 
     return m >= n; 
    } 
} 

function leq(n) { 
    return function(m) { 
     return m <= n; 
    } 
} 

var arr = [leq(9), geq(2)]; 

function check(n) { 
    arr.forEach(function(checkAgainst) { 
     console.log(checkAgainst(n)); 
    }); 
} 
+2

असल में, यह शायद सबसे सरल और सुरक्षित समाधान है।आप इसे मनमाने ढंग से जटिल मान्यताओं के लिए उपयोग कर सकते हैं, किसी भी स्पष्ट evals आदि करने की कोई आवश्यकता नहीं है। यह ES6 में भी आसान है। – Luaan

+0

अब तक यह सबसे आसान समाधान लगता है; @Luaan क्या आप ES6 वाक्यविन्यास में लिख सकते हैं? – maioman

+1

@ माईमन ईएस 6 का उपयोग करते हुए, हेल्पर्स को संक्षेप में संक्षिप्त किया जाता है, ए-ला 'var geq = (n) => {वापसी (एम) => एम> = एन; } ', लेकिन कोड का सारांश वही है। – Nit

3

मैं यह नहीं कहूंगा eval स्वाभाविक बुराई है, मैं केवल कहते हैं कि यह अपने फायदे और नुकसान है। मेरे अभ्यास में मैंने बहुत कम मामलों का अनुभव किया जहां इसके फायदे असंख्य थे।eval साथ

दो मुख्य समस्याओं:

  1. यह क्रम व्याख्या है, यानी स्ट्रिंग प्रसंस्करण और जावास्क्रिप्ट इंजन से व्याख्या की जरूरत है। यह धीमा है। सामान्य जावास्क्रिप्ट एक टोकनयुक्त रूप में चलता है।
  2. यदि आप eval का उपयोग करते हैं, तो आप एक गेम भी शुरू करते हैं जहां आप किसी भी हानिकारक कोड को अवरुद्ध करना चाहते हैं, बिना किसी कार्यक्षमता के, और हैकर्स आपके ब्लॉक के माध्यम से रास्ता खोजने की कोशिश कर रहे हैं। और आपको जानने की आपकी एकमात्र संभावना यह नहीं है कि आपकी साइट अब तक क्रैक नहीं हुई थी। आपको यह जानने की कोई संभावना नहीं है कि आपने जीता है।

लेकिन: eval मुख्य रूप से ब्राउज़र पक्ष पर चलता है, या उपयोगकर्ता इनपुट डेटा का संसाधन (एक ही उपयोगकर्ता द्वारा बनाई गई), या सर्वर डेटा जो आपके सर्वर साइड द्वारा उत्पन्न किया गया था।

आपके मामले में समाधान स्पष्ट है: उदाहरण के लिए कठिन ओओ चीजों का उपयोग करें।

function comparator(lighter, num) { 
    return function(x) { 
    return lighter ? (x<num) : (x>num); 
    } 
} 

var arr = [ comparator(true, '9'), comparator(false, '2') ]; 

var check = function(a) { 
    return arr.every(function(comp) { return comp(a); }); 
} 

console.log(check('3')); 

पहले स्थान पर इसे अपने संस्करण के रूप में और अधिक जटिल है, लेकिन यह केवल इसलिए है क्योंकि आप eval के आदी हैं और मुश्किल functor समाधान करने के लिए नहीं हैं। असल में, समाधान की जटिलता imho समान हैं।

+0

क्या आपने अभी मज़दूरों को "हार्ड ओओ" कहा था? o_o – Bergi

+0

मुझे नहीं लगता कि # 2 बहुत सटीक है। यदि आप उपयोगकर्ताओं को कोड इनपुट करने नहीं देते हैं, तो यह हैकर्स के लिए वास्तव में आसान नहीं बनाता है। और वह गेम बहुत समय पहले शुरू हुआ था, इसे 'eval' के उपयोग के साथ या बिना खेला जाता है ... – Bergi

+0

@ बर्गि हां, यह समस्या है - यदि आप कोड को प्रतिबंधित करते हैं, तो यह असफल होगा। लेकिन हमलावर इस सीमा को बाध्य नहीं कर रहे हैं, वे सब कुछ कर सकते हैं, आप केवल ऐसा कर सकते हैं जो कार्य को नुकसान नहीं पहुंचाता है। – peterh

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