javascript कौन से डिजाइन पैटर्न(जावा) जावास्क्रिप्ट के उत्थान व्यवहार का लाभ लेते हैं?




scope hoisting (8)

परिवर्तनीय उत्थापन

उत्थापन के सरलतम उपयोग में से एक चर बढ़ाना है। यदि हमारे पास चर हो जाना नहीं था, तो यह ReferenceError निकाल देगा:

var bar = foo; 
var foo;

यह तुरंत उपयोगी नहीं लगता है, लेकिन यह हमें इस तरह से करने की अनुमति देता है:

var myCoolJS = myCoolJS || {};

यह मूल रूप से इसका अर्थ होता है कि यह कैसा दिखता है: यदि myCoolJS है, तो myCoolJS है, या कोई नया ऑब्जेक्ट नहीं है। दूसरा myCoolJS एक ReferenceError नहीं फेंकता है यदि myCoolJS पहले से मौजूद नहीं था, क्योंकि यह चर घोषणा फहराया है।

यह हमें मेरे typeof myCoolJS != 'undefined' अजीब typeof myCoolJS != 'undefined' से बचाता है typeof myCoolJS != 'undefined' चेक

फंक्शन उत्थापन

एकाधिक स्क्रिप्ट को एक में संयोजन करते समय फंक्शन उत्थान विशेष रूप से उपयोगी हो सकता है उदाहरण के लिए, मैंने आम जेएस मॉड्यूल के हल्के बिल्ड-टाइम कार्यान्वयन को बनाया है I यह एक ही module प्रदान करता है, की require , और सुविधाओं को exports है जो नोड। जेएस में पाए जाते हैं। मैंने उपकरण का निर्माण किया है ताकि आवश्यक मॉड्यूल को कई फाइलों से बनाया जा सके। उदाहरण के लिए, require('/foo') की आवश्यकता दो फ़ाइलों, foo.js ("body file") और foo.h.js ("हैडर फ़ाइल") से बना एक मॉड्यूल में हो सकता है।

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

// dom.h.js

var util = require('util').util;

exports.css = css; // we can do this because "css" is hoisted from below

// ... other exports ...

...

// dom.js

function css(){}; // this would normally just be an object.

css.hasClass = function(element) { ... };
css.addClass = function(element) { ... };

// ...other code...

बेन चेरी का उत्कृष्ट लेख जावास्क्रिप्ट में उत्थापन पर्याप्त रूप से बताता है मेरी समस्या, हालांकि, यह है कि मैं भ्रम की इस कुख्यात अपराधी के लिए एक उपयोग मामला नहीं सोच सकता। कृपया बताएं कि क्या कोई डिज़ाइन पैटर्न है जो वास्तव में इस भाषा की सुविधा का लाभ उठाता है।

दूसरे, जावास्क्रिप्ट के लिए अद्वितीय स्लॉट उत्कीर्णन है?

UPDATE --- मैं एक जवाब के लिए एक इनाम जोड़ रहा हूँ जो मेरी जिज्ञासा को संतुष्ट करता है: कौन से डिजाइन पैटर्न (जावा) वास्तव में जावास्क्रिप्ट के उत्थान व्यवहार का लाभ उठाते हैं? मैं समझता हूं कि जावास्क्रिप्ट को उत्थापन का समर्थन क्यों है , लेकिन मैं जानना चाहता हूं कि मैं इस सुविधा का लाभ कैसे उठा सकता हूं


मुझे लगता है कि एक क्षेत्र जहां उत्थापन उपयोगी है, इस तथ्य के कारण यह है कि फ़ंक्शन को प्रथम श्रेणी की वस्तुओं के रूप में माना जाता है। उदाहरण के लिए:

function foo()
{
   function a()
   {
      //...
   }

   function b()
   {
      //...
   }
}

के रूप में भी लिखा जा सकता है:

function foo()
{
   var a = function ()
   {
      //...
   }

   var b = function ()
   {
      //...
   }
}

उत्थापन के बिना, निम्न के परिणामस्वरूप एक त्रुटि हो जाएगी:

function foo()
{
   var a = function ()
   {
      b();
   }
   a(); //Error in function since b is not yet defined

   var b = function ()
   {
      //...
   }
}

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


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

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

एक लूप के अंत में घोषणा के साथ (नहीं। पाठ्यक्रम के लिए निश्चित रूप से सेट गुंजाइश के रूप में) आप इसका उपयोग पहले चलने का पता लगाने के लिए कर सकते हैं।

var notfirst = true;  // this is actually never referenced.

(function () {  
  var number, stack = [1, 2, 3, 4, 5];

  while (number = stack.pop()) {
    if (notfirst) console.log(number);
    var notfirst = true;
  }
})();

स्टैक खाली करने से आउटपुट 4, 3, 2, 1 है। 5 अस्वीकार कर दिया गया है।

फिर। ऐसा मत करो!


उत्थापन के लिए यहां एक प्रयोग है:

(function() {
    var factorial = function(n) {
        if(n == 0)
            return 1;
        return n * factorial(n - 1);
    };
})();

उतार चढ़ाव के बिना, यह संकलन नहीं होता क्योंकि factorial अभी तक समारोह के अंदर मौजूद नहीं होता है। आपको अलग-अलग चर को घोषित करना होगा या नामांकित फ़ंक्शन का उपयोग करना होगा।

जावास्क्रिप्ट भी निम्नलिखित की तरह कोड की अनुमति देता है:

var test = function(b) {
    if(b) {
        var value = 2;
    } else {
        var value = 5;
    }
    console.log(value);
};

ब्लॉक स्कॉपिंग के साथ, if पहले value घोषणा करने के लिए आपको दूसरी पंक्ति जोड़नी होगी।

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

def test(b)
    # unlike JavaScript, value is not accessible here
    if b
        value = 2
    else
        value = 5
    end
    puts value
end

उस लेख के पहले दो उदाहरणों को सिर्फ बुरी तरह से लिखा गया है। खराब कोड स्पष्ट रूप से बग और भ्रम की ओर जाता है। मैं आपको इन उदाहरणों के पुनर्संचित संस्करण देता हूं। आप देखेंगे कि यहां कोई भ्रम नहीं है ...

उदाहरण 1 - मूल कोड

var foo = 1;
function bar() {
    if (!foo) {
        var foo = 10;
    }
    alert(foo);
}
bar();

उदाहरण 1 - रिफ़ेक्टेड कोड (दूषित भ्रम)

var foo = 1;

function bar() {
    var foo;

    if ( !foo ) {
        foo = 10;
    }

    alert( foo );
}

bar();

चेतावनी "10" प्रदर्शित करता है, और यह स्पष्ट क्यों है यहाँ कोई भ्रम नहीं है

उदाहरण 2 - मूल कोड

var a = 1;
function b() {
    a = 10;
    return;
    function a() {}
}
b();
alert(a);

उदाहरण 2 - रिफ़ेक्टेड कोड (दूषित भ्रम)

var a = 1;

function b() {
    var a = function () {}; 
    a = 10;
    return; 
}

b();

alert( a );

चेतावनी "1" दिखाता है जाहिर है। यहां कोई भ्रम नहीं है, बहुत


यदि आप अन्य भाषाओं को लिखी जाने वाली (सी ++ / जावा) तरीके से और उनके वर्ग के तरीकों का इस्तेमाल कैसे करते हैं, तो इसका उदहारण हो सकता है कि प्रोटोटाइप बनाने के लिए समान पैटर्न लिखने का लाभ उठाया जा सकता है।


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

यदि आप इसके बारे में सोचते हैं, तो जावास्क्रिप्ट बढ़ाना अधिक समझ में आता है।

यदि आपको उड़ाते हुए याद है, तो यह बग और भ्रम का स्रोत नहीं होना चाहिए। यह उन उन quirks में से एक है जिन्हें आपको समझना चाहिए और याद रखना चाहिए।

मुझे यकीन नहीं है कि होस्टिंग जावास्क्रिप्ट तक सीमित है। मैंने कभी इसके बारे में कभी नहीं सुना है, लेकिन इसका यह अर्थ नहीं है कि यह अन्य भाषाओं में मौजूद नहीं है।


यहां आपके लिए वास्तविक प्रयोग का मामला है (यद्यपि छद्म-कोड में कम हो गया है), जो वास्तव में जंगली में उत्थान के लाभों का उपयोग करना चाहते हैं।

मैंने हाल ही में सरल रूप सत्यापन और जमा करने के लिए इस स्क्रिप्ट को लिखा है। जहां तक ​​संभव हो, प्रत्येक फ़ंक्शन घोषणा निम्नलिखित को आमंत्रित करती है। पठनीयता के लिए इसके 2 मुख्य लाभ हैं:

  1. तार्किक क्रम : कोड के लिए एक अनुक्रमिक प्रवाह होता है, जिसका अर्थ है कि फ़ंक्शन को हमेशा घोषित किए जाने से पहले लागू किया जाएगा। यह उसमें एक लाभ है, जब कम जटिलता कार्य के साथ प्रयोग किया जाता है, यह चीजों को अपेक्षाकृत सपाट रखता है और इसके स्रोत के शीघ्र ही एक समारोह के कॉलिंग संदर्भ के बारे में आपको एक विचार देता है। आपको केवल कोड का पालन करने के लिए (कभी भी नहीं) नीचे स्क्रॉल करना होगा, और - जहां तक ​​संभव हो - सभी या बहुत कम नहीं स्क्रॉल करें
  2. कम संदर्भ ओवरहेड : मैं अपने सभी चर घोषणाओं को प्रत्येक क्षेत्र के शीर्ष पर रखना चाहूंगा ताकि पाठकों को सभी चलने वाले हिस्सों से अवगत रहना चाहिए जो कि उसके शरीर के माध्यम से पढ़ने से पहले फ़ंक्शन की आवश्यकता होती है, लेकिन कोई भी विचार प्राप्त करने के लिए हर आवंटित समारोह के स्रोत कोड को नहीं पढ़ना चाहता है वर्तमान कार्यक्षेत्र क्या करता है इस पद्धति का उपयोग करते हुए, आप इसकी घोषणा से पहले फ़ंक्शन संदर्भ में कभी नहीं चलेंगे। यह पहली बार मूर्खतापूर्ण लगता है, लेकिन यह वास्तव में संज्ञानात्मक ओवरहेड को कम कर देता है: आपको कभी भी एक समारोह का स्रोत नहीं दिया गया है जो इसे याद रखता है - हम इसे बाद में उपयोग कर रहे हैं - इसके बजाय आप केवल एक बार संदर्भ स्रोत को जानते हैं जिसे संदर्भ कहा जाता है में।
$( function emailHandler(){
  var $form      = 
  var $email     = 
  var $feedback  = 
  var value      = 
  var validation = 

  // All initialisation is right here. Executes immediately.
  // Therefore, all future code will only ever be invoked
  // by call stacks passing through here.
  void function bindEvents(){
    $email.on( 'input', filterInput );

    $form.on( 'submit', preSubmit );
  }();

  function filterInput( inputEvent ){
    if( inputEvent && inputEvent.which === '13' ){
      return presubmit( inputEvent );
    }

    return validate();
  }

  function validate(){
    var presentValue = $email.val();

    if( validation.done || presentValue === value ){
        return;
    }
    else if( presentValue === placeholder || presentValue === '' ){
        validation.message = 'You must enter an email address to sign up';
        validation.valid   = false;
    }
    else if( !validation.pattern.test( presentValue ) ){
        validation.message = 'Please enter a valid email address';
        validation.valid   = false;
    }
    else {
        validation.message = '';
        validation.valid   = true;
    }

    validation.ever = true;

    clearFeedback();
  }

  function preSubmit( inputEvent ){
    if( inputEvent instanceof $.Event ){
      inputEvent.preventDefault();
    }

    if( !validation.ever ){
      validate();
    }
    if( validation.pending || validation.done ){
      return;
    }
    else if( validation.valid ){
      return submit();
    }
    else {
      return feedback();
    }
  }

  function submit(){
    $form.addClass( 'pending' );

    // Create an XHR base on form attributes
    $.ajax( {
      cache : false,
      url   : $form.attr( 'action' ),
      data  : $form.serialize(),
      type  : $form.attr( 'method' ).toUpperCase()
    } )
      .done( success )
      .fail( failure )
      .always( feedback );
  }

  function success( response ){
    validation.message = response.message;
    validation.valid   = response.valid;
  }

  function failure(){
    validation.message = 'Our server couldn\'t sign you up. Please try again later.';
    validation.error   = true;
  }

  function feedback(){
    clearFeedback();

    if( validation.message ){
      $feedback
        .html( validation.message )
        .appendTo( $placeholder );
    }

    if( !validation.valid || validation.error ){
      $form.addClass( 'invalid' );

      $email.trigger( 'focus' );
    }
    else {
      $form.addClass( 'done' );

      validation.done = true;
    }

    validation.pending = false;
  }

  function clearFeedback(){
    $form.removeClass( 'invalid pending done' );
  }
} );






hoisting