FYI: Priveleged method gotcha

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • George Jempty

    FYI: Priveleged method gotcha

    OK, wanted to make a more positive contribution to start than just
    plonking somebody. Here's something I've discovered using "priveleged
    methods" a la Douglas Crockford
    (http://crockford.com/javascript/private.html):

    If you want a constructor to utilize priveleged methods the methods must
    be defined in the constructor ABOVE where they are called. Consider the
    following:

    function ExaminableField (element, examCriteria)
    {
    var formElement = element;
    var name = element.name;
    var required = true;

    //must be defined before used privately
    this.isRequired = function()
    {
    if (arguments.leng th == 1)
    {
    required = arguments[0]
    }
    return required;
    }

    if (!!examCriteria )
    {
    this.isRequired (examCriteria.r equired);
    }

    }

    It had been causing an error when I had my if block above the definition
    of this.isRequired . Thought this might help somebody, and/or contribute
    to a proper convention.


  • Douglas Crockford

    #2
    Re: Privileged method gotcha

    > OK, wanted to make a more positive contribution to start than just[color=blue]
    > plonking somebody. Here's something I've discovered using "priveleged
    > methods" a la Douglas Crockford
    > (http://crockford.com/javascript/private.html):
    >
    > If you want a constructor to utilize priveleged methods the methods must
    > be defined in the constructor ABOVE where they are called.[/color]

    It is generally a good thing to define things before using them. This is
    particularly true in a dynamic language like JavaScript, where the WHEN of a
    definition is significant. The critical thing is BEFORE. Often that means ABOVE,
    but not always.
    [color=blue]
    > if (!!examCriteria )[/color]

    !! converts its operand to a boolean. If it was falsy, it produces false,
    otherwise it produces true. But in an if, falsy values are ok, so the !! is
    wasted. It is better to write

    if (examCriteria)

    Comment

    • Richard Cornford

      #3
      Re: Priveleged method gotcha

      "George Jempty" <chessql@highst ream.net> wrote in message
      news:Oiy_a.782$ Q5.488@fe01.atl 2.webusenet.com ...
      <snip>[color=blue]
      > Here's something I've discovered using "priveleged
      > methods" a la Douglas Crockford
      > (http://crockford.com/javascript/private.html):
      >
      >If you want a constructor to utilize priveleged methods the
      >methods must be defined in the constructor ABOVE where they
      >are called. Consider the following:
      >
      > function ExaminableField (element, examCriteria)
      > {
      > var formElement = element;
      > var name = element.name;
      > var required = true;
      >
      > //must be defined before used privately
      > this.isRequired = function()
      > {
      > if (arguments.leng th == 1)
      > {
      > required = arguments[0]
      > }
      > return required;
      > }
      >
      > if (!!examCriteria )[/color]

      This double NOT (- !! -) is a nice construct as it produces a boolean
      that represents the type-converted true-ness of its right-most operand.
      Useful to flag the existence of a browser feature to avoid having to
      have it type-converted for multiple subsequent tests:-

      var useGetById = !!document.getE lementById;

      ( compared with clunkier looking alternatives like:-
      var useGetById = (document.getel ementById)?true :false;
      )

      - but it is not needed here. The first - ! - will have to type-convert
      its operand to a boolean value prior to inverting it, the second - ! -
      will then invert that boolean and produce the value used to resolve
      the - if - statement. However, if the identifier was used directly
      within the if statement it would be type-converted to boolean to resolve
      the - if - statement, so - if(examCriteria ) - must always produce the
      same results as - if(!!examCriter ia) - but fractionally quicker.
      [color=blue]
      > {
      > this.isRequired (examCriteria.r equired);
      > }
      >
      > }
      >
      >It had been causing an error when I had my if block above the
      >definition of this.isRequired . Thought this might help
      >somebody, and/or contribute to a proper convention.[/color]

      Because the function assigned to - this.isRequired - is a function
      expression it is evaluated inline as the constructor executes so there
      would be no value assigned to - this.isRequired - prior to the execution
      of the assignment.

      In contrast, inner function definitions (private methods in class based
      OO terminology) are evaluated during the creation of the "variable"
      object as the script enters the execution context for the function
      call[1]. So it should be possible to call such a function in code that
      physically precedes its definition and also render that function object
      privileged by assigning a reference to it to a public object member:-

      function ExaminableField (element, examCriteria){
      var formElement = element;
      var name = element.name;
      var required = true;

      if(examCriteria ){
      _requed(examCri teria.required) ;
      }

      this.isRequired = _requed;

      function _requed(){
      if(arguments.le ngth == 1){
      required = arguments[0]
      }
      return required;
      }
      }

      - Doing so seems unnecessary. I would just put up with having to write
      the constructor in the required order if I wanted the method to be
      privileged.

      [1] The Mozilla/Gecko implementation seems to be a bit off spec (ECMA
      262 3rd Edition) in this respect as it handles inner function
      definitions contained within blocks, such as - if(x){ function doX(){
      .... } } - as if they were inline in some sense. It would be unusual to
      be using inner function definitions in that way so there should be no
      significant consequences.

      Richard.


      Comment

      • Andy Fish

        #4
        Re: Priveleged method gotcha

        >[color=blue]
        > This double NOT (- !! -) is a nice construct as it produces a boolean
        > that represents the type-converted true-ness of its right-most operand.
        > Useful to flag the existence of a browser feature to avoid having to
        > have it type-converted for multiple subsequent tests:-
        >
        > var useGetById = !!document.getE lementById;
        >
        > ( compared with clunkier looking alternatives like:-
        > var useGetById = (document.getel ementById)?true :false;
        > )
        >[/color]

        I realise this is a bit OT but I find the double-not it very useful when
        validating combinations of values. For instance, if the user can specify
        either parameter a or parameter b but not both, we can write

        if ( !!a != !!b) {
        parameters are valid
        }

        obviously != transliterates into XOR. more elaborate validation rules are
        easily expressed in this way when the longhand logic would be near
        impossible to comprehend.

        This also technique is also handy in C and java.

        Andy


        Comment

        • Richard Cornford

          #5
          Re: Priveleged method gotcha

          "Andy Fish" <ajfish@blueyon der.co.uk> wrote in message
          news:hoJ_a.1115 $1l2.8482883@ne ws-text.cableinet. net...
          <snip>[color=blue]
          >... I find the double-not it very useful when
          >validating combinations of values. For instance,
          >if the user can specify either parameter a or
          >parameter b but not both, we can write[/color]
          [color=blue]
          > if ( !!a != !!b) {[/color]
          <snip>

          Consider:-
          (best viewed with fixed width font)

          a | b | a != b |
          true | false | true |
          false | true | true |
          true | true | false |
          false | false | false |

          !a | !b | !a != !b |
          false | true | true |
          true | false | true |
          false | false | false |
          true | true | false |

          !!a | !!b | !!a != !!b |
          true | false | true |
          false | true | true |
          true | true | false |
          false | false | false |

          Obviously - "aString != "anotherStr ing" - is true, while - !"aString" !=
          !"anotherString " - is false as both strings will type-convert to boolean
          true (and then be inverted to false by the - ! - operator). So at least
          one type-conversion to boolean is needed to do the comparison when a and
          b are not boolean to start with. But it looks like - !a != !b - will
          always produce the same results as - !!a != !!b - as the result of -
          !something - is always boolean.

          Richard.


          Comment

          • George Jempty

            #6
            Re: Priveleged method gotcha

            Richard Cornford wrote:[color=blue]
            > "George Jempty" <chessql@highst ream.net> wrote in message
            > news:Oiy_a.782$ Q5.488@fe01.atl 2.webusenet.com ...
            > <snip>
            >[color=green]
            >>Here's something I've discovered using "priveleged
            >>methods" a la Douglas Crockford
            >>(http://crockford.com/javascript/private.html):
            >>
            >>If you want a constructor to utilize priveleged methods the
            >>methods must be defined in the constructor ABOVE where they
            >>are called. Consider the following:
            >>
            >>function ExaminableField (element, examCriteria)
            >> {
            >> var formElement = element;
            >> var name = element.name;
            >> var required = true;
            >>
            >> //must be defined before used privately
            >> this.isRequired = function()
            >> {
            >> if (arguments.leng th == 1)
            >> {
            >> required = arguments[0]
            >> }
            >> return required;
            >> }
            >>
            >> if (!!examCriteria )[/color]
            >
            >
            > This double NOT (- !! -) is a nice construct as it produces a boolean
            > that represents the type-converted true-ness of its right-most operand.
            > Useful to flag the existence of a browser feature to avoid having to
            > have it type-converted for multiple subsequent tests:-
            >
            > var useGetById = !!document.getE lementById;
            >
            > ( compared with clunkier looking alternatives like:-
            > var useGetById = (document.getel ementById)?true :false;
            > )
            >
            > - but it is not needed here. The first - ! - will have to type-convert
            > its operand to a boolean value prior to inverting it, the second - ! -
            > will then invert that boolean and produce the value used to resolve
            > the - if - statement. However, if the identifier was used directly
            > within the if statement it would be type-converted to boolean to resolve
            > the - if - statement, so - if(examCriteria ) - must always produce the
            > same results as - if(!!examCriter ia) - but fractionally quicker.[/color]

            I use !! because examCriteria, or any other variable for that matter,
            might contain 0 or "", and I don't necessarily want these values to
            evaluate as false.

            George Jempty


            Comment

            • George Jempty

              #7
              Re: Priveleged method gotcha

              George Jempty wrote:[color=blue]
              >
              >
              > I use !! because examCriteria, or any other variable for that matter,
              > might contain 0 or "", and I don't necessarily want these values to
              > evaluate as false.[/color]

              Never mind....major brain fart


              Comment

              • Lasse Reichstein Nielsen

                #8
                Re: Priveleged method gotcha

                George Jempty <chessql@highst ream.net> writes:
                [color=blue]
                > I use !! because examCriteria, or any other variable for that matter,
                > might contain 0 or "", and I don't necessarily want these values to
                > evaluate as false.[/color]

                But they do.
                !!0 === false
                !!"" === false
                !!null === false
                !!undefined === false
                !!NaN === false

                The conversion performed by !! is exactly the same as the one
                performed by the function Boolean or implicitly by a conditional (if,
                while, do/while, ?:).

                /L
                --
                Lasse Reichstein Nielsen - lrn@hotpop.com
                Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit. html>
                'Faith without judgement merely degrades the spirit divine.'

                Comment

                • Yep

                  #9
                  Re: Priveleged method gotcha

                  "Richard Cornford" <Richard@litote s.demon.co.uk> wrote in message news:<bheu3k$pk q$1$8300dec7@ne ws.demon.co.uk> ...
                  [color=blue]
                  > [1] The Mozilla/Gecko implementation seems to be a bit off spec (ECMA
                  > 262 3rd Edition) in this respect as it handles inner function
                  > definitions contained within blocks, such as - if(x){ function doX(){
                  > ... } } - as if they were inline in some sense.[/color]

                  But they are! A function declaration is _illegal_ in a block
                  statement, therefore a function defined as you describe could be only
                  a function expression, not a function declaration, and should
                  therefore be processed as an expression. Guess which browser is a bit
                  off spec ;-)


                  Regards,
                  Yep.

                  Comment

                  • Richard Cornford

                    #10
                    Re: Priveleged method gotcha

                    "Richard Cornford" <Richard@litote s.demon.co.uk> wrote in message
                    news:bhguur$apj $1$8302bc10@new s.demon.co.uk.. .
                    <snip>[color=blue]
                    > ... . it now seems unlikely that the
                    > inner function is not being treated (correctly) ...[/color]
                    <snip>

                    The - not - in "not being treated" should not have been their. The final
                    paragraph should have read:-

                    The accessibility of the inner function by its identifier gave the
                    impression that Mozilla was treating the inner function as a function
                    declaration rather than as an expression. It now seems unlikely that
                    the inner function is being treated (correctly) as an expression but
                    that still leaves Mozilla a bit off spec on the scope chain ;-)

                    Richard.


                    Comment

                    • Yep

                      #11
                      Re: Priveleged method gotcha

                      "Richard Cornford" <Richard@litote s.demon.co.uk> wrote in message news:<bhguur$ap j$1$8302bc10@ne ws.demon.co.uk> ...
                      [color=blue]
                      > When the function object is created by the evaluation of the function
                      > expression the (optional) identifier is created as a property on a new
                      > object added to the front of the current scope chain. That scope chain
                      > is passed to the new function and the new Object is then removed from
                      > the current scope chain. That means that the only scope that can resolve
                      > the identifier for the function to a reference to the function object is
                      > the scope within that function.[/color]

                      <snip excellent illustration />

                      I see what you mean, but ISTM that this is an ECMA inconsistency, and
                      as such I won't throw the stone to Mozilla guys for making such an
                      "exception" in not respecting the specs :-)

                      Check also the amusing
                      var foo = function bar(){ alert("Guess who I am");}
                      foo(); bar();
                      which is OK in IE but not in Mozilla and Opera for which "bar" is
                      undefined (now the behavior you're expecting is correct for Mozilla,
                      the identifier is really lost).

                      It's possible to check, however, that the identifier isn't really lost
                      and is indeed kept in the scope passed to the function. Check the
                      following in Mozilla:
                      var dw=function(s){ document.write( s+"<br>")}
                      var foo = function bar(){
                      //foo.__parent__ is the local scope of foo
                      dw(foo.__parent __.bar) //now it's found!
                      dw(foo.__parent __.foo) //not found, foo is in global scope

                      //foo.__parent__. __parent__ is the global scope
                      dw(foo.__parent __.__parent__.f oo); //found, OK
                      dw(foo.__parent __.__parent__.b ar); //not found, "OK"
                      }
                      foo()


                      Cheers,
                      Yep.

                      Comment

                      • Douglas Crockford

                        #12
                        Re: Privileged method gotcha

                        > Check also the amusing[color=blue]
                        > var foo = function bar(){ alert("Guess who I am");}
                        > foo(); bar();
                        > which is OK in IE but not in Mozilla and Opera for which "bar" is
                        > undefined (now the behavior you're expecting is correct for Mozilla,
                        > the identifier is really lost).[/color]

                        And check this out in IE:

                        <html><head><sc ript>
                        var foo = function bar(){ alert(bar.ok);}
                        foo.ok = 'correct';
                        foo();
                        </script></head></html>

                        IE puts the function name in the wrong scope. It should go in the inner scope,
                        but instead is put in the outer scope.



                        Comment

                        • Yep

                          #13
                          Re: Privileged method gotcha

                          "Douglas Crockford" <nospam@laserli nk.net> wrote in message news:<bhil5o$na 6$1@sun-news.laserlink. net>...
                          [color=blue]
                          > And check this out in IE:
                          >
                          > <html><head><sc ript>
                          > var foo = function bar(){ alert(bar.ok);}
                          > foo.ok = 'correct';
                          > foo();
                          > </script></head></html>
                          >
                          > IE puts the function name in the wrong scope. It should go in the inner scope,
                          > but instead is put in the outer scope.[/color]

                          Actually IE seems to evaluate the "function bar" twice, the first time
                          as a function declaration, the second time as a function expression
                          (where it doesn't add the identifier to the inner scope chain - it
                          even does nothing with the identifier); as a result foo and bar aren't
                          even equal.

                          Add
                          bar.ok = "Hello?"
                          at the beginning of your script to have an illustration.


                          Regards,
                          Yep.

                          Comment

                          Working...