Which design pattern(s) take advantage of JavaScri

2019-01-30 10:28发布

Ben Cherry's excellent article explains hoisting in JavaScript adequately. My problem, however, is that I cannot conceive a use case for this notorious perpetrator of confusion. Please explain if there is a design pattern that actually takes advantage of this language feature.

Secondly, is scope hoisting unique to JavaScript?

UPDATE --- I'm adding a bounty for an answer that satisfies my curiosity: Which design pattern(s) actually take advantage of JavaScript's hoisting behavior? I understand why JavaScript supports hoisting, but I want to know how I can take advantage of this feature.

9条回答
手持菜刀,她持情操
2楼-- · 2019-01-30 11:30

JavaScript does not have block scope (let's forget about let for now) and thus any variable declaration is declaring for the entire function, of which JavaScript does have scope.

If you think about it that way, JavaScript hoisting may make more sense.

If you remember about hoisting, it shouldn't be a source of bugs and confusion. It's simply one of those quirks you must understand and remember.

I'm not sure if hoisting is limited to JavaScript. I've never heard of it elsewhere, but that doesn't necessarily mean it doesn't exist in other languages.

查看更多
虎瘦雄心在
3楼-- · 2019-01-30 11:32

Here's a real use case (albeit reduced to pseudo-code) for you, from someone who would actually want to use the benefits of hoisting in the wild.

I recently wrote this script for handling simple form validation and submission. As far as possible, each function declaration invokes the following. This has 2 chief benefits for readability:

  1. Logical sequence: there is a sequential flow to the code, which means functions will always be invoked before they are declared. This is a benefit in that, when used with low complexity functions, it keeps things relatively flat and gives you an idea of the calling context of a function shortly before its source. You will only ever have to scroll down (never up) to follow code, and — as far as possible — scroll not at all or very little.
  2. Low reference overhead: I like to keep all my variable declarations at the top of each scope so readers are aware of all the moving parts the function requires before reading through its body, but nobody wants to read every invoked function's source code to get an idea of what the current scope does. Using this method, you'll never run into a function reference before its declaration. It sounds stupid at first, but it actually reduces cognitive overhead: you're never given a function's source with the implicit remember this — we'll be using it later — instead you only ever read function source once you know the context it was called in.
$( 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' );
  }
} );
查看更多
放荡不羁爱自由
4楼-- · 2019-01-30 11:33

"hoisting" is not part of the ECMAScript Standard, but it does say that variable inside a function are declared at the begin of the function regardless of where in the function it is place in the code.

Example

(function() {
  alert(myvar); // undefined
  var myvar = 'local value';
})();

Internally Javascript would declare myvar before the alert, show the alert, then it would assign myvar to 'local value'.

So Javascript would interpet that code as:

(function() {
  var myvar;
  alert(myvar); // undefined
  myvar = 'local value';
})();

That is why "Java the Good parts" has a guideline that say you should declare variable at the top of your function.

Source: http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-hoisting-explained/

"Please explain if there is a design pattern that actually takes advantage of this language feature." "hoisting" is not a feature but rather a consequence how the Javascript interpreter structure the code since the language uses function-scoping.

"Which design pattern(s) actually take advantage of JavaScript's hoisting behavior? " Answer: None.

查看更多
登录 后发表回答