क्या जावास्क्रिप्ट के "कथन" के लिए वैध उपयोग हैं?


369

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

आपने withकथन को कहाँ उपयोगी पाया है ?


52
मैं इसका इस्तेमाल कभी नहीं करता। अगर मैं दिखावा करता हूं, तो इसके बिना जीना आसान है।
नोसरेडना

6
एक बार इसके लिए कई वैध उपयोग हो सकते हैं। लेकिन यह लूट है। ईएस 5 सख्त हटा दिया गया है withइसलिए अब ऐसी कोई बात नहीं है।
थॉमस आयलॉट

27
यहाँ ध्यान देने योग्य बात यह है कि ES5 सख्त अभी भी वैकल्पिक है
शोग

5
ES5 सख्त में 'के साथ' को हटाने के बजाय, क्या मानक को बदलना बेहतर नहीं होगा ताकि यदि कोई चर नहीं मिलता है, तो 'के साथ' के अंदर किया गया कोई भी असाइनमेंट तर्क ऑब्जेक्ट के लिए बाध्य है?
जूसीआर

2
@ जुस्सी: शायद। लेकिन ऐसा करने में समस्या यह है कि यह संभवतः पुराने ब्राउज़रों में चीजों को तोड़ देगा।
सून रासमुसेन

जवाबों:


520

आज मेरे लिए एक और उपयोग हुआ, इसलिए मैंने उत्साह से वेब को खोजा और इसका एक मौजूदा उल्लेख पाया: ब्लॉक स्कोप के अंदर चर को परिभाषित करना

पृष्ठभूमि

जावास्क्रिप्ट, सी और सी ++ के लिए अपने सतही समानता के बावजूद, उन चरों के लिए वैरिएबल नहीं है, जिन्हें वे परिभाषित करते हैं:

var name = "Joe";
if ( true )
{
   var name = "Jack";
}
// name now contains "Jack"

लूप में क्लोजर की घोषणा करना एक सामान्य कार्य है जहां इससे त्रुटियां हो सकती हैं:

for (var i=0; i<3; ++i)
{
   var num = i;
   setTimeout(function() { alert(num); }, 10);
}

क्योंकि लूप के लिए एक नया स्कोप पेश नहीं किया जाता है, वही num- जिसके मान के साथ 2- सभी तीन कार्यों द्वारा साझा किया जाएगा।

एक नया दायरा: letऔरwith

ईएस 6let में बयान की शुरुआत के साथ, इन समस्याओं से बचने के लिए आवश्यक होने पर एक नया दायरा पेश करना आसान हो जाता है:

// variables introduced in this statement 
// are scoped to each iteration of the loop
for (let i=0; i<3; ++i)
{
   setTimeout(function() { alert(i); }, 10);
}

या और भी:

for (var i=0; i<3; ++i)
{
   // variables introduced in this statement 
   // are scoped to the block containing it.
   let num = i;
   setTimeout(function() { alert(num); }, 10);
}

जब तक ईएस 6 सार्वभौमिक रूप से उपलब्ध नहीं होता है, तब तक यह उपयोग नवीनतम ब्राउज़रों और डेवलपर्स तक सीमित रहता है, जो ट्रांसपैरर्स का उपयोग करने के लिए तैयार हैं। हालाँकि, हम आसानी से इस व्यवहार का अनुकरण कर सकते हैं with:

for (var i=0; i<3; ++i)
{
   // object members introduced in this statement 
   // are scoped to the block following it.
   with ({num: i})
   {
      setTimeout(function() { alert(num); }, 10);
   }
}

लूप अब इरादा के अनुसार काम करता है, 0 से 2 तक के मूल्यों के साथ तीन अलग-अलग चर बना रहा है। ध्यान दें कि ब्लॉक के भीतर घोषित किए गए चर सी + + में ब्लॉक के व्यवहार के विपरीत, इसे शुरू नहीं किया जाना चाहिए। एक ब्लॉक, इसलिए एक तरह से यह समान है)। यह व्यवहार वास्तव में मोज़िला ब्राउज़र के पुराने संस्करणों में पेश किए गए एक letब्लॉक सिंटैक्स के समान है, लेकिन व्यापक रूप से कहीं और नहीं अपनाया गया है।


15
शाब्दिक के साथ उपयोग करने के बारे में कभी नहीं सोचा, कानूनी लगता है।
मैट कांटोर

81
यह वास्तव में वास्तव में मृत है। मैंने इस तरह से जावास्क्रिप्ट के दायरे के साथ खेलने के बारे में कभी नहीं सोचा है। मेरे कोडिंग के लिए पूरी तरह से नए क्षेत्रों का विस्तार किया। काश मैं 10 बार उत्थान कर पाता!
kizzx2

27
अभी भी विरोध करने वालों के लिए, कोई हमेशा बंद का उपयोग कर सकता है:for (var i = 0; i < 3; ++i) { setTimeout ((function () { var num = i; return function () { alert (num); }; }) (), 10);}
थॉमस एडिंग

4
दरअसल, ऊपर लिंक की गई समस्या अधिकांश गैर-मोज़िला ब्राउज़र (क्रोम, सफारी, ओपेरा, IE) पर दिखाई देती है।
मैक्स श्वाबकेह

24
जाने IE में बयान समर्थन वास्तव में अभी मेरी बेकन की बचत होगी, मैं या नहीं, का उपयोग करने पर मेरी अंतरात्मा की आवाज के साथ संघर्ष कर रहा हूँ के साथ बजाय। वास्तविक समस्या यह है कि एक लेट के साथ भी, प्रोटोटाइप श्रृंखला पर किसी वस्तु के विरासत में मिले गुणों के कारण अतिरिक्त देखभाल अभी भी की जानी है। उदाहरण के लिए, । के दायरे में साथ बयान, toString () की एक विरासत संपत्ति है वस्तु है, तो स्पष्ट रूप से परिभाषित समारोह नहीं बुलाया जाता है। फिर भी एक शानदार जवाब, हालांकि :-)var toString = function () { return "Hello"; }; with ({"test":1}) { console.log(toString()); };
एंडी ई

161

मैं स्टेटमेंट के साथ स्कोप इम्पोर्ट के सरल फॉर्म के रूप में उपयोग कर रहा हूं। मान लीजिए कि आपके पास किसी प्रकार का एक मार्कअप बिल्डर है। लिखने के बजाय:

markupbuilder.div(
  markupbuilder.p('Hi! I am a paragraph!',
    markupbuilder.span('I am a span inside a paragraph')
  )
)

आप इसके बजाय लिख सकते हैं:

with(markupbuilder){
  div(
    p('Hi! I am a paragraph!',
      span('I am a span inside a paragraph')
    )
  )
}

इस उपयोग के मामले में, मैं कोई असाइनमेंट नहीं कर रहा हूं, इसलिए मुझे इससे जुड़ी अस्पष्टता की समस्या नहीं है।


5
मैंने देखा है कि यह VB में कैसे इस्तेमाल होता है। (और केवल एक ही उपयोग जो मुझे पता था।)
मतीन उल्हाक

2
इसका नकारात्मक पक्ष यह होगा कि यदि आप ब्लॉक के साथ एक वैरिएबल का संदर्भ देते हैं जो मार्कअप बिल्डर ऑब्जेक्ट के बाहर है, तो जेएस इंजन पहले प्रदर्शन मार्कअप को वैसे भी मार्कअप बिल्डर के अंदर खोजेगा।
एडम थॉमस

3
यह वास्तव में कैनवास पथ के साथ काम करने वालों के लिए कोड में कटौती करने में मदद करता है।
ब्रायन मैकूचिऑन

4
उस कोड का "विथ" संस्करण शाब्दिक रूप से मेरी मशीन पर "गैर-के साथ" संस्करण की तुलना में 240 गुना अधिक धीमा है। यही कारण है कि लोगों का कहना है कि इसके लिए कोई वैध उपयोग नहीं है। इसलिए नहीं कि यह कुछ स्थानों में कोड को पूर्ववर्ती नहीं बना सकता है। बेंचमार्क देखें: jsfiddle.net/sc46eeyn
जिम्बो जॉनी

1
@McBrainy - यह वास्तव में उस जगह का प्रकार है जिसे आपको कोड का उपयोग नहीं करना चाहिए जो मल्टीटाउन स्लो चलाता है (टिप्पणी मैं सिर्फ इस एक के ऊपर बनाया गया है) देखें। यदि आपको सुपर बार-बार कोड के लिए शॉर्टकट चाहिए तो आप उन्हें घोषित कर सकते हैं। उदाहरण के लिए यदि context.bezierCurveToएक सौ बार सीधे प्रयोग करके आप कह सकते हैं var bc2 = context.bezierCurveTo;और फिर bc2(x,x,etc);हर बार जब आप इसे कॉल करना चाहते हैं तो जाएं। यह काफी तेज़ और कम क्रिया है, जबकि withयह सुपर स्लो है।
जिम्बो जॉनी

83

जैसा कि मेरी पिछली टिप्पणियों ने संकेत दिया है, मुझे नहीं लगता कि आप withकिसी भी स्थिति में किसी भी तरह से लुभावने तरीके से सुरक्षित रूप से उपयोग कर सकते हैं । चूँकि समस्या सीधे यहाँ पर नहीं है, इसलिए मैं इसे दोहराऊंगा। निम्नलिखित कोड पर विचार करें

user = {};
someFunctionThatDoesStuffToUser(user);
someOtherFunction(user);

with(user){
    name = 'Bob';
    age  = 20;
}

उन फ़ंक्शन कॉल की सावधानीपूर्वक जांच के बिना, यह बताने का कोई तरीका नहीं है कि इस कोड के चलने के बाद आपके कार्यक्रम की स्थिति क्या होगी। अगर user.nameपहले से सेट था, तो अब होगा Bob। यदि यह सेट नहीं किया गया था, तो वैश्विक nameको प्रारंभ या बदल दिया जाएगा Bobऔर userऑब्जेक्ट बिना nameसंपत्ति के रहेगा ।

कीड़े होते हैं। यदि आप अपने साथ उपयोग करते हैं तो अंततः ऐसा करेंगे और आपके कार्यक्रम में असफलता बढ़ेगी। इससे भी बदतर, आप काम करने वाले कोड का सामना कर सकते हैं जो ब्लॉक के साथ वैश्विक रूप से सेट करता है, या तो जानबूझकर या लेखक के माध्यम से इस निर्माण के बारे में नहीं जानता है। यह एक स्विच पर गिरने का सामना करने की तरह है, आपको पता नहीं है कि लेखक ने यह इरादा किया है और यह जानने का कोई तरीका नहीं है कि "फिक्सिंग" कोड एक प्रतिगमन का परिचय देगा।

आधुनिक प्रोग्रामिंग भाषाओं को सुविधाओं से भरा है। कुछ विशेषताएं, उपयोग के वर्षों के बाद, खराब होने के लिए खोजी जाती हैं, और इनसे बचा जाना चाहिए। जावास्क्रिप्ट withउनमें से एक है।


18
यह समस्या केवल सतहों की है जब आप ऑब्जेक्ट की विशेषता के लिए मान असाइन कर रहे हैं। लेकिन क्या होगा यदि आप इसे केवल मूल्यों को पढ़ने के लिए उपयोग कर रहे हैं? मैं तर्क देता हूं कि उस स्थिति में इसका उपयोग करना ठीक है।
हवाई

10
टॉबी के मूल्यों को पढ़ने के लिए भी यही समस्या लागू होती है। उपरोक्त कोड स्निपेट में आप नहीं जानते कि क्या नाम उपयोगकर्ता ऑब्जेक्ट पर सेट है, इसलिए आपको नहीं पता होगा कि क्या आप वैश्विक नाम या उपयोगकर्ता नाम पढ़ रहे हैं।
एलन स्टॉर्म

12
मूल्यों को पढ़ने के साथ एक स्पष्ट पूर्ववर्ती नियम है: ऑब्जेक्ट पर विशेषताओं को दायरे से बाहर चर से पहले जांचा जाता है। यह फ़ंक्शंस में स्कूपिंग से भिन्न नहीं है। असाइनमेंट और 'के साथ' के साथ वास्तविक समस्या, जैसा कि मैं इसे समझता हूं, इस तथ्य में निहित है कि विशेषता असाइनमेंट होता है या नहीं, यह निर्भर करता है कि क्या विशेषता वर्तमान वस्तु पर मौजूद है, जो एक रनटाइम संपत्ति है और आसानी से कटौती नहीं की जा सकती है कोड को देखकर।
हवाई

1
मुझे लगता है कि तुम वहीं हो सकते हो टोबी। मेरे लिए पूरी तरह से निर्माण से दूर रहने के लिए लेखन समस्या पर्याप्त है।
एलन स्टॉर्म

"यह एक स्विच पर गिरने से सामना करने जैसा बहुत कुछ है, आपको कोई पता नहीं है ..." - तो फिर चलो स्विच () पर प्रतिबंध लगा दें? ; पप
सझ।

66

मैंने withहाल ही में बयान को अविश्वसनीय रूप से उपयोगी पाया । यह तकनीक वास्तव में मेरे लिए कभी नहीं हुई जब तक कि मैंने अपनी वर्तमान परियोजना शुरू नहीं की - जावास्क्रिप्ट में लिखा एक कमांड लाइन कंसोल। मैं Firebug / WebKit कंसोल API का अनुकरण करने की कोशिश कर रहा था जहां विशेष कमांड को कंसोल में दर्ज किया जा सकता है लेकिन वे वैश्विक दायरे में किसी भी चर को ओवरराइड नहीं करते हैं। मैंने इस बारे में सोचा जब मैंने एक समस्या को दूर करने की कोशिश की, जो मैंने शोग 9 के उत्कृष्ट उत्तर के लिए टिप्पणियों में उल्लेख किया ।

इस प्रभाव को प्राप्त करने के लिए, मैंने बयानों के साथ दो का उपयोग किया "वैश्विक गुंजाइश के पीछे एक परत"

with (consoleCommands) {
    with (window) {
        eval(expression); 
    }
}

इस तकनीक के बारे में महान बात यह है कि, प्रदर्शन के नुकसान से अलग, यह withबयान की सामान्य आशंकाओं को सहन नहीं करता है , क्योंकि हम वैसे भी वैश्विक दायरे में मूल्यांकन कर रहे हैं - हमारे छद्म दायरे से बाहर चर का कोई खतरा नहीं है संशोधित।

मुझे यह उत्तर पोस्ट करने के लिए प्रेरित किया गया, जब मेरे आश्चर्य करने के लिए, मैं उसी तकनीक को कहीं और इस्तेमाल करने में कामयाब रहा - क्रोमियम स्रोत कोड !

InjectedScript._evaluateOn = function(evalFunction, object, expression) {
    InjectedScript._ensureCommandLineAPIInstalled();
    // Surround the expression in with statements to inject our command line API so that
    // the window object properties still take more precedent than our API functions.
    expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }";
    return evalFunction.call(object, expression);
}

संपादित करें: बस फायरबग स्रोत की जांच की, वे 4 परतों को एक साथ और अधिक परतों के लिए एक साथ बयान करते हैं। पागल!

const evalScript = "with (__win__.__scope__.vars) { with (__win__.__scope__.api) { with (__win__.__scope__.userVars) { with (__win__) {" +
    "try {" +
        "__win__.__scope__.callback(eval(__win__.__scope__.expr));" +
    "} catch (exc) {" +
        "__win__.__scope__.callback(exc, true);" +
    "}" +
"}}}}";

1
लेकिन चिंता है कि ecmascript5 आपको ऐसा करने से रोकता है। वहाँ एक पारिस्थितिकी 5 समाधान है?
कीर्बनेटिको

@ एडम: मैं उस बारे में निश्चित नहीं हूं। ES5 केवल सख्त मोड में इसके लिए कोई त्रुटि देता है, इसलिए यदि आपके पास वैश्विक स्तर पर सख्त मोड घोषित नहीं है, तो यह तत्काल मुद्दा नहीं है। ES सद्भाव एक बड़ी समस्या पैदा कर सकता है, लेकिन यह कुछ नए सामान जैसे परदे के पीछे से ठीक हो सकता है।
एंडी ई

@AndyE खेद है कि यह बंद विषय है, लेकिन क्या आपका 'कमांड लाइन कंसोल जावास्क्रिप्ट में लिखा है' कहीं भी उपलब्ध है?
18:00 पर kybernetikos

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

3
कुछ हफ्ते पहले हमने क्रोम में अपने कंसोल कार्यान्वयन को ब्लॉक से कुछ प्रतीक जादू के साथ स्थानांतरित कर दिया क्योंकि ब्लॉक ने कुछ ES6 सुविधाओं को अवरुद्ध कर दिया :)
एलेक्सी कोज़ीतिंसकी

54

हाँ, हाँ और हाँ। बहुत वैध उपयोग है। घड़ी:

with (document.getElementById("blah").style) {
    background = "black";
    color = "blue";
    border = "1px solid green";
}

मूल रूप से किसी भी अन्य डोम या सीएसएस हुक के साथ शानदार उपयोग कर रहे हैं। यह ऐसा नहीं है कि "CloneNode" अपरिभाषित होगा और वैश्विक दायरे में वापस आ जाएगा जब तक कि आप अपने रास्ते से बाहर नहीं गए और इसे संभव बनाने का फैसला किया।

क्रॉकफोर्ड की गति की शिकायत यह है कि इसके साथ एक नया संदर्भ बनाया जाता है। संदर्भ आम तौर पर महंगे होते हैं। मैं सहमत हूँ। लेकिन अगर आपने सिर्फ एक div बनाया है और अपने css को सेट करने के लिए हाथ पर कुछ फ्रेमवर्क नहीं है और 15 या तो CSS गुणों को हाथ से सेट करने की आवश्यकता है, तो एक संदर्भ बनाना संभवत: सस्ता होगा, फिर वैरिएबल क्रिएशन और 15 डेफरेंस:

var element = document.createElement("div"),
    elementStyle = element.style;

elementStyle.fontWeight = "bold";
elementStyle.fontSize = "1.5em";
elementStyle.color = "#55d";
elementStyle.marginLeft = "2px";

आदि...


5
+1 जैसा कि मुझे भी लगता है कि इसके बहुत सारे वैध उपयोग हैं with। हालाँकि, इस विशेष मामले में आप बस कर सकते हैं:element.style.cssText="background: black ; color: blue ; border: 1px solid green"
GetFree

5
आप extendjQuery या Underscore.js से सरल विधि का उपयोग करके एक पंक्ति में एक ही चीज़ प्राप्त कर सकते हैं $.extend(element.style, {fontWeight: 'bold', fontSize: '1.5em', color: '#55d', marginLeft: '2px'}):।
ट्रेवर बर्नहैम

9
@TrevorBurnham - यदि आप मान लें कि jQuery उपलब्ध है, तो आप बस इसकी .css()विधि का उपयोग करेंगे ...
nnnnnn

4
क्या वास्तव में इन चरों को वैश्विक दायरे में जाने से रोक रहा है? क्या यह सिर्फ इसलिए है क्योंकि सभी सीएसएस शैलियों को हमेशा सभी तत्वों पर परिभाषित किया जाता है, या क्या?
मप्र

1
@ मर्क हाँ, उन्हें हमेशा परिभाषित किया जाता है, अगर किसी संपत्ति के लिए कोई कस्टम शैली नहीं है, तो मानों के रूप में नल या खाली तार के साथ
Esailija

34

withअस्पष्टता के बिना लाभ प्रदान करने के लिए आप एक छोटे सहायक कार्य को परिभाषित कर सकते हैं :

var with_ = function (obj, func) { func (obj); };

with_ (object_name_here, function (_)
{
    _.a = "foo";
    _.b = "bar";
});

8
OMG, मेरे सिर का विस्तार! अस्पष्टता के बिना ? मत देना कि ऊपर, आदमी!
जारोड डिक्सन

@ जरारोड: इस ( is.gd/ktoZ ) के बारे में क्या मज़ेदार है ? इस साइट का उपयोग करने वाले सभी लोग मुझसे अधिक स्मार्ट हैं, इसलिए यदि मैं गलत हूं तो मुझे माफ़ कर दें, लेकिन यह बुरी जानकारी है।
रैवेन

14
लेकिन ऐसा करने के तरीके को समझने में अभी लंबा और कठिन है: var _ = obj_name_here; _.a = "foo"; _.b = "बार;
रेने सरसो

3
रेने: इसके साथ, आप "_" वैरिएबल को बाहरी दायरे में लाएंगे, जिसके परिणामस्वरूप संभावित बग हो जाएंगे। यह ऑब्जेक्ट पैरामीटर की गणना में उपयोग किए गए किसी भी अस्थायी चर को भी उजागर करेगा।
जॉन मिलिकिन

30
आपको with_एक मैला दोगुना संस्करण (function(_){ _.a="foo"; })(object_here);(सी / जावा-शैली ब्लॉकों को अनुकरण करने का मानक तरीका) होने से अधिक कीड़े मिलेंगे । इसके बजाय उसका उपयोग करें।
एमके।

25

शायद ही आप इस लायक हैं क्योंकि आप निम्न कार्य कर सकते हैं:

var o = incrediblyLongObjectNameThatNoOneWouldUse;
o.name = "Bob";
o.age = "50";

1
इससे मुझे कोई मतलब नहीं था। हालांकि मैं जावास्क्रिप्ट में एक विशेषज्ञ नहीं हूं
JeroenEijkhof

@WmasterJ स्पष्टता के लिए, यह पोस्ट देखें: yuiblog.com/blog/2006/04/11/with-statement-considered-harmful
डेनिस

8
लंबे चर नाम केवल के लिए उपयोग का मामला नहीं है with
क्रिस

18

मैं कभी भी इसका उपयोग नहीं करता, इसके लिए कोई कारण नहीं देखता, और इसकी अनुशंसा नहीं करता।

इसके साथ समस्या withयह है कि यह कई शाब्दिक अनुकूलन को रोकता है जो एक ECMAScript कार्यान्वयन प्रदर्शन कर सकता है। तेजी से JIT- आधारित इंजनों के उदय को देखते हुए, यह मुद्दा संभवतः निकट भविष्य में और भी महत्वपूर्ण हो जाएगा।

ऐसा लग सकता है कि withक्लीनर निर्माण के लिए अनुमति देता है (जब, कहते हैं, एक सामान्य अनाम फ़ंक्शन आवरण के स्थान पर एक नया स्कोप पेश करना या क्रिया अलियासिंग को बदलना), लेकिन यह वास्तव में इसके लायक नहीं है । घटे हुए प्रदर्शन के अलावा, हमेशा एक गलत वस्तु की संपत्ति को आवंटित करने का खतरा होता है (जब किसी वस्तु को इंजेक्शन के दायरे में नहीं पाया जाता है) और शायद गलत तरीके से वैश्विक चर पेश कर रहा है। IIRC, बाद वाला मुद्दा वह है जिसने क्रॉकफोर्ड को बचने की सलाह देने के लिए प्रेरित किया with


6
प्रदर्शन बोगीमैन को अक्सर बाहर हो जाता है, लगभग जितनी बार ग्लोबल्स की बात होती है ... हमेशा मुझे अजीब लगता है, यह देखते हुए कि यह जावास्क्रिप्ट है जिसके बारे में हम बात कर रहे हैं। आपको लगता है कि प्रदर्शन हिट वास्तव में नाटकीय है कि बहुत ध्यान देने योग्य है, लेकिन ... यदि आपके पास with(){}निर्माण की लागत पर कोई कठिन संख्या है जैसे कि अन्य उत्तर में यहां दिए गए आधुनिक ब्राउज़रों में, मैं देखना पसंद करूंगा उन्हें!
शोग

6
यह जावास्क्रिप्ट के संदर्भ में क्यों अजीब है? :) और हाँ, यह नाटकीय है। इसके बारे में सोचो - एक कार्यान्वयन को कोष्ठक में एक अभिव्यक्ति का मूल्यांकन करने की आवश्यकता है, इसे ऑब्जेक्ट में परिवर्तित करें, इसे वर्तमान स्कोप चेन के सामने डालें, ब्लॉक के अंदर स्टेटमेंट का मूल्यांकन करें, फिर स्कोप चेन को सामान्य में वापस लाएं। वह बहुत काम की चीज है। एक साधारण संपत्ति देखने की तुलना में बहुत अधिक है जिसे एक उच्च-अनुकूलित निम्न स्तर कोड में बदल दिया जा सकता है। यहाँ एक बहुत ही सरल बेंचमार्क है जो मैंने अभी बनाया है (मुझे पता है कि क्या आपको कोई ग़लती मिलती है) अंतर को प्रदर्शित करते हुए - gist.github.com/c36ea485926806020024
kangax

5
@ केंक्सक्स: मैं एक सी ++ बैकग्राउंड से आता हूं, जहां कई प्रोग्रामर के लिए अपने कोड में छोटी क्षमता के बारे में देखना पारंपरिक के समान है, यहां तक ​​कि जब वे वास्तव में बड़े रूटीन या प्रोग्राम के प्रदर्शन पर ध्यान देने योग्य प्रभाव नहीं रखते हैं। यह मुझे जावास्क्रिप्ट के संदर्भ में अजीब लगता है, जहां दिनचर्या के प्रदर्शन का इतना बड़ा हिस्सा वीएम कार्यान्वयन पर निर्भर हो सकता है। मैंने कुछ उदाहरणों को देखा है जहां जेएस प्रोग्रामर सेटअप लागत पर चिंताओं के कारण एक अनाम फ़ंक्शन से बचेंगे, लेकिन यह अपवाद नहीं लगता है, कोड के बहुत संवेदनशील क्षेत्रों के लिए आरक्षित है।
शोग

5
उस ने कहा, आप लागत के संबंध में बिलकुल सही हैं with(){}: withमेरे द्वारा परीक्षण किए गए प्रत्येक ब्राउज़र पर एक नया स्कोप स्थापित करना बेहद महंगा है। आप बहुत बार कहे जाने वाले किसी भी कोड में इससे बचना चाहेंगे। इसके अलावा, क्रोम ने एक with()दायरे के भीतर किसी भी कोड को निष्पादित करने के लिए एक नाटकीय हिट प्रदर्शित किया । दिलचस्प है, IE में with()ब्लॉकों के भीतर कोड के लिए सबसे अच्छा प्रदर्शन विशेषताओं थे : सेटअप लागत को बाहर करना, with()IE6 और IE8 VMs में सदस्य अभिगम का सबसे तेज़ साधन प्रदान करता है (हालांकि ये VM कुल मिलाकर सबसे धीमे हैं)। अच्छा सामान, धन्यवाद ...
शोग

5
FWIW: यहां सेटअप लागत के साथ परीक्षणों का एक ही सेट फैक्टर आउट किया गया है: jsbin.com/imidu/edit के लिए चर तक पहुंच with()लगभग क्रोम में परिमाण धीमे का क्रम है, और IE में दो बार उपवास ...!
शोग

13

Visual Basic.NET का Withकथन समान है। मेरे द्वारा उपयोग किए जाने वाले अधिक सामान्य तरीकों में से एक है जल्दी से कई गुणों को सेट करना। के बजाय:

someObject.Foo = ''
someObject.Bar = ''
someObject.Baz = ''

, मैं लिख सकता हूँ:

With someObject
    .Foo = ''
    .Bar = ''
    .Baz = ''
End With

यह सिर्फ आलस्य की बात नहीं है। यह बहुत अधिक पठनीय कोड भी बनाता है। और जावास्क्रिप्ट के विपरीत, यह अस्पष्टता से ग्रस्त नहीं है, क्योंकि आपको एक .(डॉट) के साथ बयान से प्रभावित सब कुछ उपसर्ग करना होगा । तो, निम्नलिखित दो स्पष्ट रूप से अलग हैं:

With someObject
    .Foo = ''
End With

बनाम

With someObject
    Foo = ''
End With

पूर्व है someObject.Foo; उत्तरार्द्ध बाहरFoo के दायरे में है । someObject

मुझे लगता है कि जावास्क्रिप्ट की कमी की कमी विजुअल बेसिक के संस्करण की तुलना में इसे कम उपयोगी बनाती है, क्योंकि अस्पष्टता का जोखिम बहुत अधिक है। इसके अलावा, withअभी भी एक शक्तिशाली विचार है जो बेहतर पठनीयता के लिए बना सकता है।


2
आधी हकीकत। हालांकि उनके सवाल का जवाब नहीं है। तो यह विषय से दूर है।
एलन लालोंड

6
मेरे दिमाग में भी यही चल रहा था। किसी को यह कहना था । जावास्क्रिप्ट केवल डॉट के रूप में अच्छी तरह से क्यों नहीं कर सकता।
कार्सन मायर्स

सहमत, डॉट नोटेशन बेहतर है, काश जावास्क्रिप्ट इसका इस्तेमाल करता। +1

8

आप withकिसी ऑब्जेक्ट की सामग्री को स्थानीय चर के रूप में एक ब्लॉक में पेश करने के लिए उपयोग कर सकते हैं , जैसे कि यह इस छोटे टेम्पलेट इंजन के साथ किया जा रहा है ।


1
इस तकनीक का उपयोग अंडरस्कोर .js के _.template () में भी किया जा रहा है ।
पीटर वी। मॉरच

7

"के साथ" का उपयोग करना आपके कोड को और अधिक शुष्क बना सकता है।

निम्नलिखित कोड पर विचार करें:

var photo = document.getElementById('photo');
photo.style.position = 'absolute';
photo.style.left = '10px';
photo.style.top = '10px';

आप इसे निम्न में सुखा सकते हैं:

with(document.getElementById('photo').style) {
  position = 'absolute';
  left = '10px';
  top = '10px';
}

मुझे लगता है कि यह निर्भर करता है कि क्या आपके पास सुगम्यता या अभिव्यक्ति के लिए प्राथमिकता है।

पहला उदाहरण अधिक सुपाठ्य है और संभवतः अधिकांश कोड के लिए अनुशंसित है। लेकिन ज्यादातर कोड वैसे भी बहुत टैम है। दूसरा एक अधिक अस्पष्ट है, लेकिन कोड आकार और शानदार रूपों में कटौती करने के लिए भाषा की अभिव्यंजक प्रकृति का उपयोग करता है।

मैं उन लोगों की कल्पना करता हूं जो जावा या सी # पसंद करते हैं (ऑब्जेक्ट.member) पहला तरीका चुनते हैं और जो लोग रूबी या पायथन पसंद करते हैं वे बाद वाले को चुनेंगे।


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

6

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

(with-slots (foo bar) objectname
   "some code that accesses foo and bar"

जो लिखने जैसा है

"some code that accesses (slot-value objectname 'foo) and (slot-value objectname 'bar)""

यह अधिक स्पष्ट है कि यह एक शॉर्टकट क्यों है जब आपकी भाषा "Objectname.foo" की अनुमति देती है लेकिन फिर भी।


1
लिस्प कोड देखने के लिए महान! मुझे लगता है कि जावास्क्रिप्ट में "के साथ" स्पष्ट रूप से यह एक भाषा के रूप में योजना की जड़ों से प्रेरित है, लेकिन यह है कि आपके जावास्क्रिप्ट प्रश्न पर LISP पोस्ट करने के लिए अस्वीकृत हो रहा है।
आग कौवा

1
मूल सिद्धांत पर उत्थान। 'के साथ' एक अभूतपूर्व शक्तिशाली निर्माण है। लेकिन अधिकांश JS लोग क्लोज़र को नहीं समझते हैं, और JS के शीर्ष पर हास्यास्पद रूप से जटिल जावा क्लास इनहेरिटेंस सिस्टम लिखते हैं - तो उन्हें मेटाप्रोग्रामिंग क्षमता के बारे में कैसे पता चल सकता है कि 'ऑफर' के साथ?
jared

बेशक with-slotsआपको यह निर्दिष्ट करने की आवश्यकता है कि आप कौन से स्लॉट का उपयोग कर रहे हैं, जबकि withरनटाइम पर बाध्य होने के लिए जो भी स्लॉट होते हैं उनका उपयोग करेगा।
सैमुअल एडविन वार्ड

6

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

Scoping समस्याओं को आप के ज़्यादा इस्तेमाल से में प्राप्त कर सकते हैं के साथ बयान एक में एक शाही दर्द हो सकता है ** और मैं किसी को भी यह पता लगाने की एक डिबगिंग सत्र का अनुभव नहीं करना चाहेंगे कि वह क्या .. अपने कोड में चल रहा है , केवल यह पता लगाने के लिए कि इसने आपके वैश्विक या बाहरी स्कोप वैरिएबल के बजाय किसी ऑब्जेक्ट मेंबर या गलत लोकल वैरिएबल को कैप्चर किया है, जिसका आपने इरादा किया है।

कथन के साथ VB बेहतर है, इसमें डॉट्स को स्कोपिंग को डिसबैलेंस करने की आवश्यकता होती है, लेकिन डेल्फी स्टेटमेंट के साथ एक लोडेड बंदूक होती है, और यह मुझे ऐसा लगता है जैसे कि जावास्क्रिप्ट एक ही चेतावनी वारंट के समान है।


5
कथन के साथ जावास्क्रिप्ट डेल्फी एक से भी बदतर है। डेल्फी में, ऑब्जेक्ट.member संकेतन की तुलना में केवल तेज़ (यदि तेज़ नहीं है) प्रदर्शन करता है। जावास्क्रिप्ट में, मिलान करने वाले सदस्यों के लिए जाँच करने के लिए स्कोप चलना पड़ता है, इस प्रकार यह हमेशा ऑब्जेक्ट.member संकेतन की तुलना में धीमा हो जाता है।
मार्टिज़न

5

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

स्रोत: Mozilla.org


4

कथन के साथ कोड आकार को कम करने के लिए या निजी वर्ग के सदस्यों के लिए इस्तेमाल किया जा सकता है, उदाहरण:

// demo class framework
var Class= function(name, o) {
   var c=function(){};
   if( o.hasOwnProperty("constructor") ) {
       c= o.constructor;
   }
   delete o["constructor"];
   delete o["prototype"];
   c.prototype= {};
   for( var k in o ) c.prototype[k]= o[k];
   c.scope= Class.scope;
   c.scope.Class= c;
   c.Name= name;
   return c;
}
Class.newScope= function() {
    Class.scope= {};
    Class.scope.Scope= Class.scope;
    return Class.scope;
}

// create a new class
with( Class.newScope() ) {
   window.Foo= Class("Foo",{
      test: function() {
          alert( Class.Name );
      }
   });
}
(new Foo()).test();

यदि आप इस दायरे को संशोधित करना चाहते हैं, तो स्टेटमेंट के साथ बहुत उपयोगी है, जो आपके स्वयं के वैश्विक दायरे के लिए आवश्यक है कि आप रनटाइम में हेरफेर कर सकते हैं। आप इस पर स्थिरांक या कुछ सहायक कार्यों का उपयोग कर सकते हैं, जैसे कि अक्सर "toUpper", "tolower" या "Number "," clipNumber "aso ।।

खराब प्रदर्शन के बारे में मैंने पढ़ा है कि अक्सर: किसी फ़ंक्शन को स्कोप करने से प्रदर्शन पर कोई प्रभाव नहीं पड़ेगा, वास्तव में मेरे FF में एक स्कॉप्ड फ़ंक्शन तेजी से चलता है फिर एक अनकैप्ड:

var o={x: 5},r, fnRAW= function(a,b){ return a*b; }, fnScoped, s, e, i;
with( o ) {
    fnScoped= function(a,b){ return a*b; };
}

s= Date.now();
r= 0;
for( i=0; i < 1000000; i++ ) {
    r+= fnRAW(i,i);
}
e= Date.now();
console.log( (e-s)+"ms" );

s= Date.now();
r= 0;
for( i=0; i < 1000000; i++ ) {
    r+= fnScoped(i,i);
}
e= Date.now();
console.log( (e-s)+"ms" );

इसलिए उपर्युक्त तरीके से उपयोग किए गए कथन के साथ प्रदर्शन पर कोई नकारात्मक प्रभाव नहीं पड़ता है, लेकिन यह एक अच्छा है क्योंकि यह कोड आकार को कम करता है, जो मोबाइल उपकरणों पर मेमोरी के उपयोग को प्रभावित करता है।


3

के साथ प्रयोग करने से आपका कोड कई कार्यान्वयन में धीमा हो जाता है, क्योंकि अब सब कुछ देखने के लिए एक अतिरिक्त दायरे में लिपटा हुआ है। जावास्क्रिप्ट में उपयोग करने का कोई वैध कारण नहीं है।


5
समय से पहले अनुकूलन। जब तक आप संख्याओं में कमी नहीं करते हैं, तब तक "धीमे" होने का दावा न करें; किसी भी ओवरहेड की संभावना आधुनिक और प्राचीन दोनों जाटों पर है।
एमके।

2
मैं आपके निष्कर्ष से पूरी तरह असहमत हूं, जो इस बात पर आधारित है कि आपके अलावा अन्य डेवलपर्स के लिए कोई समस्या नहीं हो सकती है।
डेव वान डे आईंड

4
@ एमके: ठीक है, यहां आपके लिए नंबर क्रंचिंग: var obj={a:0,b:0,c:0};var d=+new Date;with(obj){for(var i=0;i<1000000;++i){a+=1;b+=1;c+=1}}+new Date-d;औसत 2500 var obj={a:0,b:0,c:0};var d=+new Date;for(var i=0;i<1000000;++i){obj.a+=1;obj.b+=1;obj.c+=1}+new Date-d;पर देता है , जबकि औसत 750 पर देता है , जबकि 3 बार धीमी गति से उपयोग करने वाला।
योरिक

3
जब मैंने यह देखा तो बस इन्हें Chrome 23 में चलाया गया था। मुझे मिले परिणाम 1138 थेwith कोड के और बिना 903 के थे। एक तंग पाश में भी इस छोटे अंतर के साथ मैं प्रदर्शन के बारे में चिंता करने से पहले केस-बाय-केस आधार पर सरलता और कोडिंग को आसान बनाने के आधार पर चयन करूंगा।
पिल्लेक्स

3

मुझे लगता है कि एक टेम्पलेट भाषा को जावास्क्रिप्ट में परिवर्तित करने के साथ-साथ कथन काम में आ सकता है। उदाहरण के लिए JST में base2 , लेकिन मैं इसे अधिक बार देखा है।

मैं मानता हूं कि कोई भी बिना बयान के यह कार्यक्रम कर सकता है। लेकिन क्योंकि यह कोई समस्या नहीं देता है यह एक वैध उपयोग है।


3

यह एक कंटेनर में अपेक्षाकृत जटिल वातावरण में चलने वाले कोड को डालने के लिए अच्छा है: मैं इसका उपयोग "विंडो" के लिए एक स्थानीय बंधन बनाने के लिए करता हूं और इस तरह के कोड को वेब ब्राउज़र के लिए चलाने के लिए।


3

मुझे लगता है कि वस्तु शाब्दिक उपयोग दिलचस्प है, जैसे एक बंद करने के लिए ड्रॉप-इन प्रतिस्थापन

for(var i = nodes.length; i--;)
{
       // info is namespaced in a closure the click handler can access!
       (function(info)
       {           
            nodes[i].onclick = function(){ showStuff(info) };
       })(data[i]);
}

या एक बंद के बयान के साथ

for(var i = nodes.length; i--;)
{
       // info is namespaced in a closure the click handler can access!
       with({info: data[i]})
       {           
            nodes[i].onclick = function(){ showStuff(info) };
       }        
}

मुझे लगता है कि वास्तविक जोखिम आकस्मिक रूप से छोटे चर हैं जो कथन का हिस्सा नहीं हैं, यही वजह है कि मुझे ऑब्जेक्ट शाब्दिक के साथ पारित किया जा रहा है, आप यह देख सकते हैं कि कोड में जोड़े गए संदर्भ में यह वास्तव में क्या होगा।


3

मैंने एक "मर्ज" फ़ंक्शन बनाया, जो withकथन के साथ इस अस्पष्टता को समाप्त करता है:

if (typeof Object.merge !== 'function') {
    Object.merge = function (o1, o2) { // Function to merge all of the properties from one object into another
        for(var i in o2) { o1[i] = o2[i]; }
        return o1;
    };
}

मैं इसे इसी तरह उपयोग कर सकते हैं with , लेकिन मैं जान सकता हूं कि यह किसी भी दायरे को प्रभावित नहीं करेगा, जिसे प्रभावित करने के लिए मैं इसका इरादा नहीं करता हूं।

उपयोग:

var eDiv = document.createElement("div");
var eHeader = Object.merge(eDiv.cloneNode(false), {className: "header", onclick: function(){ alert("Click!"); }});
function NewObj() {
    Object.merge(this, {size: 4096, initDate: new Date()});
}

3

कुछ शॉर्ट कोड टुकड़े के लिए, मैं की तरह त्रिकोणमितीय कार्यों का उपयोग करना चाहते हैं sin, cosडिग्री मोड में बजाय उज्ज्वल मोड में आदि। इस उद्देश्य के लिए, मैं एक AngularDegreeवस्तु का उपयोग करता हूं :

AngularDegree = new function() {
this.CONV = Math.PI / 180;
this.sin = function(x) { return Math.sin( x * this.CONV ) };
this.cos = function(x) { return Math.cos( x * this.CONV ) };
this.tan = function(x) { return Math.tan( x * this.CONV ) };
this.asin = function(x) { return Math.asin( x ) / this.CONV };
this.acos = function(x) { return Math.acos( x ) / this.CONV };
this.atan = function(x) { return Math.atan( x ) / this.CONV };
this.atan2 = function(x,y) { return Math.atan2(x,y) / this.CONV };
};

फिर मैं किसी withखंड में बिना किसी भाषा शोर के डिग्री मोड में त्रिकोणमितीय कार्यों का उपयोग कर सकता हूं :

function getAzimut(pol,pos) {
  ...
  var d = pos.lon - pol.lon;
  with(AngularDegree) {
    var z = atan2( sin(d), cos(pol.lat)*tan(pos.lat) - sin(pol.lat)*cos(d) );
    return z;
    }
  }

इसका मतलब है: मैं एक ऑब्जेक्ट का उपयोग फ़ंक्शन के संग्रह के रूप में करता हूं, जिसे मैं सीधे पहुंच के लिए एक सीमित कोड क्षेत्र में सक्षम करता हूं। मुझे यह उपयोगी लगता है।


withइस तरह से कथन का उपयोग करने के लिए एक अच्छा विचार नहीं है , यह सिर्फ पढ़ने के लिए कोड को कठिन बनाता है क्योंकि आपको पता नहीं है कि कौन सा फ़ंक्शन वैश्विक है और किस फ़ंक्शन को ऑब्जेक्ट के दायरे में कहा जाता है, इसलिए यदि किसी भी फ़ंक्शन को किसी भी तरह से परिभाषित नहीं किया गया है ऑब्जेक्ट स्कोप तब इसे वैश्विक नामस्थान
साकेत पटेल

स्कूपिंग की समस्या से अवगत होने के बाद भी मुझे यह उपयोगी लगता है। कोड को पढ़ने वाला एक गणितज्ञ सीधे देखना चाहता है कि उपरोक्त सूत्र गोलाकार त्रिकोणमिति में "4 क्रमिक भागों के कानून" का एक अनुप्रयोग है। सख्त विकल्प सूत्र को बाधित करता है: z = Math.atan2( Math.sin(d * Math.PI / 180), Math.cos( pol.lat * Math.PI / 180) * Math.tan( pos.lat * Math.PI / 180 ) - Math.sin( pol.lat * Math.PI / 180 ) * Math.cos( d * Math.PI / 180) ) * 180 / Math.PI;एक ही परिणाम देगा, लेकिन यह डरावनी है।
रोपिलिको

@rplantiko ध्यान रखने वाली बात यह है कि ज्यादातर लोग इसके साथ सहज महसूस नहीं करते हैं। इसलिए जब तक आप कोड नहीं लिख रहे हैं कि कोई और कभी नहीं छूएगा। इसके अलावा, मुझे पूरा यकीन है कि मैं आपको कुछ ऐसा दिखा सकता हूं जो आपको रोक withदेगा।
जुआन मेंडेस

2

मुझे लगता है कि आपकी उपयोगिता इस बात withपर निर्भर कर सकती है कि आपका कोड कितना अच्छा लिखा गया है। उदाहरण के लिए, यदि आप ऐसा कोड लिख रहे हैं जो इस प्रकार दिखाई देता है:

var sHeader = object.data.header.toString();
var sContent = object.data.content.toString();
var sFooter = object.data.footer.toString();

तब आप तर्क दे सकते हैं कि withऐसा करने से कोड की पठनीयता में सुधार होगा:

var sHeader = null, sContent = null, sFooter = null;
with(object.data) {
    sHeader = header.toString();
    sContent = content.toString();
    sFooter = content.toString();
}

इसके विपरीत, यह तर्क दिया जा सकता है कि आप कानून के कानून का उल्लंघन कर रहे हैं , लेकिन, फिर से, शायद नहीं। मैं पचाता हूं =)।

इन सबसे ऊपर, यह जान लें कि डगलस क्रॉकफ़ोर्ड उपयोग नहीं करने की सलाह देता है with। मैं आपसे आग्रह करता हूं कि आप withइसके बारे में और इसके विकल्पों के बारे में अपने ब्लॉग पोस्ट की जाँच करें


प्रतिक्रिया के लिए धन्यवाद, टॉम। मैंने क्रॉकफोर्ड की सिफारिश पढ़ी है, और जबकि यह समझ में आता है कि यह केवल इतनी दूर जाता है। मैं इस विचार के इर्द-गिर्द आ रहा हूं - डॉकमैन द्वारा अप्रत्यक्ष रूप से छुआ गया - कि {} की वास्तविक शक्ति उस तरीके से है, जिसका उपयोग गुंजाइश में हेरफेर करने के लिए किया जा सकता है ...
Shog9

2

मैं वास्तव में यह नहीं देखता कि कैसे उपयोग करने से किसी भी प्रकार से अधिक पठनीय है। मुझे नहीं लगता कि यह कोई कम पठनीय है, लेकिन मुझे नहीं लगता कि यह किसी भी अधिक पठनीय है।

जैसा कि लेस्सेवेक ने कहा, मैं निश्चित रूप से यह देख सकता हूं कि किस तरह से उपयोग करने से अधिक स्पष्ट रूप से त्रुटि हो जाएगी "ऑब्जेक्ट.member" सिंटैक्स।


1

आपको W3schools http://www.w3schools.com/js/js_form_validation.asp पर जावास्क्रिप्ट में एक फॉर्म के सत्यापन को देखने के लिए मिला है, जहां 'ईमेल' नाम से एक इनपुट खोजने के माध्यम से ऑब्जेक्ट फॉर्म "स्कैन" किया गया है

लेकिन मैंने इसे किसी भी रूप से प्राप्त करने के लिए संशोधित कर दिया है, जो किसी भी रूप में नाम या क्षेत्र की मात्रा की परवाह किए बिना सभी फ़ील्डों को मान्य नहीं है। वैसे मैंने केवल टेक्स्ट-फील्ड का परीक्षण किया है।

लेकिन () ने चीजों को सरल बना दिया। यहाँ कोड है:

function validate_required(field)
{
with (field)
  {
  if (value==null||value=="")
    {
    alert('All fields are mandtory');return false;
    }
  else
    {
    return true;
    }
  }
}

function validate_form(thisform)
{
with (thisform)
  {
    for(fiie in elements){
        if (validate_required(elements[fiie])==false){
            elements[fiie].focus();
            elements[fiie].style.border='1px solid red';
            return false;
        } else {elements[fiie].style.border='1px solid #7F9DB9';}
    }

  }
  return false;
}

1

CoffeeScript के कोको फोर्क में एक withकीवर्ड है, लेकिन यह बस ब्लॉक के भीतर लक्ष्य ऑब्जेक्ट के लिए this( @कॉफीस्क्रिप्ट / कोको के रूप में भी लिखने योग्य) सेट करता है । यह अस्पष्टता को दूर करता है और ES5 सख्त मोड अनुपालन को प्राप्त करता है:

with long.object.reference
  @a = 'foo'
  bar = @b

0

यहाँ के लिए एक अच्छा उपयोग है with : ऑब्जेक्ट ऑब्जेक्ट में नए तत्वों को जोड़ना, उस ऑब्जेक्ट में संग्रहीत मानों के आधार पर। यहाँ एक उदाहरण है जो मैंने अभी उपयोग किया है:

मेरे पास संभव टाइलों का एक सेट था (ऊपर, नीचे, बाएं या दाएं तरफ खुलने के साथ) जिसका उपयोग किया जा सकता था, और मुझे टाइलों की एक सूची जोड़ने का एक त्वरित तरीका चाहिए था जिसे हमेशा खेल की शुरुआत में रखा और बंद किया जाएगा। । मैं types.tbrसूची में प्रत्येक प्रकार के लिए टाइपिंग नहीं रखना चाहता था , इसलिए मैंने इसका उपयोग किया with

Tile.types = (function(t,l,b,r) {
  function j(a) { return a.join(' '); }
  // all possible types
  var types = { 
    br:  j(  [b,r]),
    lbr: j([l,b,r]),
    lb:  j([l,b]  ),  
    tbr: j([t,b,r]),
    tbl: j([t,b,l]),
    tlr: j([t,l,r]),
    tr:  j([t,r]  ),  
    tl:  j([t,l]  ),  
    locked: []
  };  
  // store starting (base/locked) tiles in types.locked
  with( types ) { locked = [ 
    br,  lbr, lbr, lb, 
    tbr, tbr, lbr, tbl,
    tbr, tlr, tbl, tbl,
    tr,  tlr, tlr, tl
  ] } 
  return types;
})("top","left","bottom","right");

0

आवश्यकता होने पर स्पष्टता का प्रबंधन करने के लिए आप इसका उपयोग कर सकते हैं।

var modules = requirejs.declare([{
    'App' : 'app/app'
}]);

require(modules.paths(), function() { with (modules.resolve(arguments)) {
    App.run();
}});

आवश्यकता के कार्यान्वयन:

requirejs.declare = function(dependencyPairs) {
    var pair;
    var dependencyKeys = [];
    var dependencyValues = [];

    for (var i=0, n=dependencyPairs.length; i<n; i++) {
        pair = dependencyPairs[i];
        for (var key in dependencyPairs[i]) {
            dependencyKeys.push(key);
            dependencyValues.push(pair[key]);
            break;
        }
    };

    return {
        paths : function() {
            return dependencyValues;
        },

        resolve : function(args) {
            var modules = {};
            for (var i=0, n=args.length; i<n; i++) {
                modules[dependencyKeys[i]] = args[i];
            }
            return modules;
        }
    }   
}

0

जैसा कि एंडी ई ने शोग 9 के उत्तर की टिप्पणियों में बताया है, withएक वस्तु शाब्दिक के साथ उपयोग करते समय यह संभावित-अप्रत्याशित व्यवहार होता है :

for (var i = 0; i < 3; i++) {
  function toString() {
    return 'a';
  }
  with ({num: i}) {
    setTimeout(function() { console.log(num); }, 10);
    console.log(toString()); // prints "[object Object]"
  }
}

ऐसा नहीं है कि अप्रत्याशित व्यवहार पहले से ही इसकी पहचान नहीं थी with

यदि आप वास्तव में अभी भी इस तकनीक का उपयोग करना चाहते हैं, तो कम से कम एक अशक्त प्रोटोटाइप के साथ एक वस्तु का उपयोग करें।

function scope(o) {
  var ret = Object.create(null);
  if (typeof o !== 'object') return ret;
  Object.keys(o).forEach(function (key) {
    ret[key] = o[key];
  });
  return ret;
}

for (var i = 0; i < 3; i++) {
  function toString() {
    return 'a';
  }
  with (scope({num: i})) {
    setTimeout(function() { console.log(num); }, 10);
    console.log(toString()); // prints "a"
  }
}

लेकिन यह केवल ES5 + में काम करेगा। भी उपयोग न करें with


0

मैं एक ऐसे प्रोजेक्ट पर काम कर रहा हूं, जो उपयोगकर्ताओं को एप्लिकेशन के कुछ हिस्सों के व्यवहार को संशोधित करने के लिए कोड अपलोड करने की अनुमति देगा। इस परिदृश्य में, मैं withअपने कोड को उस दायरे से बाहर कुछ भी संशोधित करने से रोकने के लिए एक क्लॉज का उपयोग कर रहा हूं जो मैं चाहता हूं कि उनके साथ गड़बड़ हो। यह करने के लिए मेरे द्वारा उपयोग किए जाने वाले कोड का सरल (सरल) भाग है:

// this code is only executed once
var localScope = {
    build: undefined,

    // this is where all of the values I want to hide go; the list is rather long
    window: undefined,
    console: undefined,
    ...
};
with(localScope) {
    build = function(userCode) {
        eval('var builtFunction = function(options) {' + userCode + '}');
        return builtFunction;
    }
}
var build = localScope.build;
delete localScope.build;

// this is how I use the build method
var userCode = 'return "Hello, World!";';
var userFunction = build(userCode);

यह कोड सुनिश्चित करता है (कुछ हद तक) कि उपयोगकर्ता-परिभाषित कोड की न तो किसी भी वैश्विक रूप से स्कैन की गई वस्तुओं तक पहुंच है windowऔर न ही मेरे किसी स्थानीय वेरिएबल्स में किसी क्लोजर के माध्यम से।

बुद्धिमान के लिए एक शब्द के रूप में, मुझे अभी भी उपयोगकर्ता-प्रस्तुत कोड पर स्थिर कोड जांच करना है ताकि यह सुनिश्चित हो सके कि वे वैश्विक स्कोप का उपयोग करने के लिए अन्य डरपोक शिष्टाचार का उपयोग नहीं कर रहे हैं। उदाहरण के लिए, निम्नलिखित उपयोगकर्ता-परिभाषित कोड सीधे पहुंच प्रदान करता है window:

test = function() {
     return this.window
};
return test();


0

मेरे

switch(e.type) {
    case gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED: blah
    case gapi.drive.realtime.ErrorType.CLIENT_ERROR: blah
    case gapi.drive.realtime.ErrorType.NOT_FOUND: blah
}

उबल जाता है

with(gapi.drive.realtime.ErrorType) {switch(e.type) {
    case TOKEN_REFRESH_REQUIRED: blah
    case CLIENT_ERROR: blah
    case NOT_FOUND: blah
}}

क्या आप इतने कम गुणवत्ता वाले कोड पर भरोसा कर सकते हैं? नहीं, हम देखते हैं कि इसे बिल्कुल अपठनीय बनाया गया था। यह उदाहरण निर्विवाद रूप से साबित करता है कि यदि मुझे पठनीयता सही है, तो बयान की कोई आवश्यकता नहीं है;)

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