Function Context

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Brett Foster

    Function Context

    Perhpas somebody can give me a hand with this little problem.

    Given:

    var object; -- an object
    var func; -- a function call back

    Now, I want to know how to get the following effect:

    object.func = func;
    object.func();

    function func (somethingelse) {
    this.something = somethingelse;
    }

    such that 'this' referes to 'object' without having to make 'func' a
    member of 'object'. I tried `with (object) {func ();}` which I realized
    wouldn't do that job.

    Thanks,

    Brett Foster
  • Michael Winter

    #2
    Re: Function Context

    On Fri, 07 Jan 2005 16:01:40 -0500, Brett Foster
    <fosterb.no.s.p .a.m@ioctl.ca> wrote:

    [snip]
    [color=blue]
    > object.func = func;
    > object.func();
    >
    > function func (somethingelse) {
    > this.something = somethingelse;
    > }[/color]

    func.call(objec t);

    extending the call to include any arguments that the function, func,
    should receive.

    If this is for general Internet use (or for any environment that features
    any JScript version earlier than 5.5 [which usually means IE5 or
    earlier]), you should be prepared to emulate the call method:

    if(Function.pro totype
    && ('function' != typeof Function.protot ype.call))
    {
    Function.protot ype.call = function(o) {var p = '__call', r;
    while('undefine d' != typeof o[p]) {p += p;}
    o[p] = this; r = o[p](); delete o[p]; return r;
    };
    }

    If the object in question might be a host object (such as an element
    reference), remove the while statement and delete operator (otherwise IE
    will error) and don't use the same property name contained in the local
    variable, p.

    [snip]

    Hope that helps,
    Mike

    --
    Michael Winter
    Replace ".invalid" with ".uk" to reply by e-mail.

    Comment

    • Got Scripting?

      #3
      Re: Function Context

      Michael Winter wrote:[color=blue]
      > On Fri, 07 Jan 2005 16:01:40 -0500, Brett Foster
      > <fosterb.no.s.p .a.m@ioctl.ca> wrote:
      >
      > [snip]
      >[color=green]
      > > object.func = func;
      > > object.func();
      > >
      > > function func (somethingelse) {
      > > this.something = somethingelse;
      > > }[/color]
      >
      > func.call(objec t);
      >
      > extending the call to include any arguments that the function, func,[/color]
      [color=blue]
      > should receive.[/color]

      OK, this is especially interesting in that I was about to ask a quite
      similar question. However, I want to know how to use "call()" (or
      apply()) from within an object constructor function.

      Below is some code. In the second constructor, "FormExam", I'd like to
      replace the existing line of code, with a call to either call() or
      apply(), to acheive the same effect.

      The example in Rhino, as I recall off the top of my head, says
      "this.call(...) ", but this results in an error message that the method
      is not defined. I've also tried FormExam.call(. ..) and
      BaseFormExam.ca ll(....), but these too result in errors. What am I
      doing wrong, or do I just need to leave it the way it is below (if it
      ain't broke, don't fix it)?

      Thanks in advance


      function BaseFormExam(_f orm, _criteria) {
      var criteria = _criteria;
      var input = _form;

      this._passes = function() {
      //stub
      return false;
      }
      }

      function FormExam(_form, _criteria) {
      this.base = BaseFormExam; this.base(_form , _criteria); delete
      this.base;
      }

      Comment

      • Michael Winter

        #4
        Re: Function Context

        On 7 Jan 2005 15:33:46 -0800, Got Scripting? <scriptify@yaho o.com> wrote:

        [snip]

        As a quick note, it's best to indent and manually wrap code.
        [color=blue]
        > function BaseFormExam(_f orm, _criteria) {
        > var criteria = _criteria;
        > var input = _form;[/color]

        Why don't you use the arguments instead of creating local variables which
        contain the same values. There would be no difference in behaviour.

        [snip]
        [color=blue]
        > function FormExam(_form, _criteria) {
        > this.base = BaseFormExam; this.base(_form , _criteria);
        > delete this.base;
        > }[/color]

        The same effect would be acheived with

        function FormExam(_form, _criteria) {
        BaseFormExam.ca ll(this, _form, _criteria);
        }

        This certainly works in browsers. I don't know about Rhino (assuming
        that's your target environment).

        Good luck,
        Mike

        --
        Michael Winter
        Replace ".invalid" with ".uk" to reply by e-mail.

        Comment

        • Got Scripting?

          #5
          Re: Function Context

          Michael Winter wrote:[color=blue]
          > On 7 Jan 2005 15:33:46 -0800, Got Scripting? <scriptify@yaho o.com>[/color]
          wrote:[color=blue]
          >
          > As a quick note, it's best to indent and manually wrap code.[/color]

          um, my code simply lost its formatting when cutting and pasting into
          google group's textarea (i'll have to keep this in mind for future
          posts)
          [color=blue]
          > Why don't you use the arguments instead of creating local variables[/color]
          which[color=blue]
          > contain the same values. There would be no difference in behaviour.[/color]

          ok that's a good idea, see below
          [color=blue][color=green]
          > > function FormExam(_form, _criteria) {
          > > this.base = BaseFormExam; this.base(_form , _criteria);
          > > delete this.base;
          > > }[/color]
          >
          > The same effect would be acheived with
          >
          > function FormExam(_form, _criteria) {
          > BaseFormExam.ca ll(this, _form, _criteria);
          > }[/color]

          in light of your "good idea" above, then I also decided to try:

          BaseFormExam.ap ply(this, arguments);

          since apply takes an array; worked like a charm. I also believe it's
          Javascript 1.2 compliant?!
          [color=blue]
          > This certainly works in browsers. I don't know about Rhino (assuming[/color]
          [color=blue]
          > that's your target environment).[/color]

          Your example certainly did work. Sorry about the confusion. I meant
          the Rhino book (Flanagan's "Javascript : The Definitive Guide"), rather
          than the Rhino implementation.

          Many thanks!!

          Comment

          • Michael Winter

            #6
            Re: Function Context

            On 7 Jan 2005 16:17:26 -0800, Got Scripting? <scriptify@yaho o.com> wrote:
            [color=blue]
            > Michael Winter wrote:[/color]

            [snip]
            [color=blue][color=green]
            >> function FormExam(_form, _criteria) {
            >> BaseFormExam.ca ll(this, _form, _criteria);
            >> }[/color]
            >
            > in light of your "good idea" above, then I also decided to try:
            >
            > BaseFormExam.ap ply(this, arguments);
            >
            > since apply takes an array; worked like a charm. I also believe it's
            > Javascript 1.2 compliant?![/color]

            I don't have a Netscape reference to hand, but something like that.
            However, Microsoft didn't implement it until JScript 5.5 (so usually IE5.5
            or later). It might be easier to use the call method with the emulation I
            showed earlier (though you'll have to modify it slightly to take - and to
            use - arguments).
            [color=blue][color=green]
            >> This certainly works in browsers. I don't know about Rhino (assuming
            >> that's your target environment).[/color]
            >
            > I meant the Rhino book (Flanagan's "Javascript : The Definitive Guide"),
            > rather than the Rhino implementation.[/color]

            It's OK. I had Rhino (Moz) stuck in my head from an earlier thread. :)
            [color=blue]
            > Many thanks!![/color]

            You're welcome.

            Mike

            --
            Michael Winter
            Replace ".invalid" with ".uk" to reply by e-mail.

            Comment

            • Got Scripting?

              #7
              Re: Function Context

              Michael Winter wrote:[color=blue]
              > On 7 Jan 2005 16:17:26 -0800, Got Scripting? <scriptify@yaho o.com>[/color]
              wrote:[color=blue]
              >[color=green][color=darkred]
              > >> function FormExam(_form, _criteria) {
              > >> BaseFormExam.ca ll(this, _form, _criteria);
              > >> }[/color]
              > >
              > > in light of your "good idea" above, then I also decided to try:
              > >
              > > BaseFormExam.ap ply(this, arguments);
              > >
              > > since apply takes an array; worked like a charm. I also believe[/color][/color]
              it's[color=blue][color=green]
              > > Javascript 1.2 compliant?![/color]
              >
              > I don't have a Netscape reference to hand, but something like that.
              > However, Microsoft didn't implement it until JScript 5.5 (so usually[/color]
              IE5.5[color=blue]
              > or later). It might be easier to use the call method with the[/color]
              emulation I[color=blue]
              > showed earlier (though you'll have to modify it slightly to take -[/color]
              and to[color=blue]
              > use - arguments).[/color]

              Well this has certainly been enlightening. apply() seems the most
              elegant for my particular usage, but the implementation limitations of
              apply() and call() may just make me stick with my original:

              this.base = BaseFormExam; this.base(_form , _criteria); delete
              this.base;

              Inelegant? Yes. But to me, simpler than hacking Function's prototype.
              Though its still good to learn different approaches ;)

              Comment

              • Richard Cornford

                #8
                Re: Function Context

                Michael Winter wrote:
                <snip>[color=blue]
                > if(Function.pro totype
                > && ('function' != typeof Function.protot ype.call))
                > {
                > Function.protot ype.call = function(o) {var p = '__call', r;
                > while('undefine d' != typeof o[p]) {p += p;}
                > o[p] = this; r = o[p](); delete o[p]; return r;
                > };
                > }
                >
                > If the object in question might be a host object (such as an
                > element reference), remove the while statement and delete
                > operator (otherwise IE will error) and don't use the same
                > property name contained in the local variable, p.[/color]
                <snip>

                As I recall, the problem with IE's host objects is that they error on
                the delete statement. I wonder whether assigning - Undefined - (the
                current value of an unassigned local variable should do for that) would
                be sufficient. In the event that the object did already have a property
                name that coincided with (possibly repeated) '__call' then it would have
                to be - Undefined - at the start of the execution of the - call -
                emulation, and would be re-assigned - Undefined - at the end, which
                should be (mostly) harmless.

                Richard.



                Comment

                • Michael Winter

                  #9
                  Re: Function Context

                  On Sat, 8 Jan 2005 12:31:12 -0000, Richard Cornford
                  <Richard@litote s.demon.co.uk> wrote:

                  [snip]
                  [color=blue]
                  > As I recall, the problem with IE's host objects is that they error on
                  > the delete statement.[/color]

                  Yes, that's what I was trying to imply. Evidently Microsoft don't bother
                  with the internal attributes set forth in ECMA-262 and treat all
                  properties on host objects as DontDelete. Why they had to flag an error
                  rather than returning false is beyond me, though.

                  [alternative deletion suggestion]

                  if(Function.pro totype
                  && ('function' != typeof Function.protot ype.call))
                  {
                  Function.protot ype.call = function(o) {var p = '__call', r, u;
                  while('undefine d' != typeof o[p]) {p += p;}
                  o[p] = this; r = o[p](); o[p] = u; return r;
                  };
                  }

                  An alternative to an uninitialised local variable would be void operator
                  which always evaluates to undefined.

                  This might be an odd question to ask, Richard, but am I checking for the
                  prototype object for any particular reason? I'm sure there *is* a reason -
                  and I'd assume that it's due to the provisions of ECMA-327 - but I've
                  completely forgotten. It's just become something I feel compelled to do.

                  Mike

                  --
                  Michael Winter
                  Replace ".invalid" with ".uk" to reply by e-mail.

                  Comment

                  • Richard Cornford

                    #10
                    Re: Function Context

                    Michael Winter wrote:
                    <snip>[color=blue]
                    > This might be an odd question to ask, Richard, but am I
                    > checking for the prototype object for any particular reason?
                    > I'm sure there *is* a reason - and I'd assume that it's due
                    > to the provisions of ECMA-327 - but I've completely forgotten.
                    > It's just become something I feel compelled to do.[/color]
                    <snip>

                    It would take either a very odd, or extremely old, script implementation
                    for the Function.protot ype to be missing (and the old ones are so old
                    that you wouldn't have - typeof - to test with anyway). However,
                    verifying Function.protot ype doesn't seem a bad thing to be doing,
                    though logic would suggest verifying - Function - as well. It will
                    prevent the script from erring-out at the following test and is only
                    done once. Though if either Function or Function.protot ype were missing
                    then the script would likely error-out when call was later executed.

                    Richard.


                    Comment

                    • Brett Foster

                      #11
                      Re: Function Context

                      Michael Winter wrote:[color=blue]
                      > On Fri, 07 Jan 2005 16:01:40 -0500, Brett Foster
                      > <fosterb.no.s.p .a.m@ioctl.ca> wrote:
                      >
                      > [snip]
                      >[color=green]
                      >> object.func = func;
                      >> object.func();
                      >>
                      >> function func (somethingelse) {
                      >> this.something = somethingelse;
                      >> }[/color]
                      >
                      >
                      > func.call(objec t);
                      >
                      > extending the call to include any arguments that the function, func,
                      > should receive.
                      >
                      > If this is for general Internet use (or for any environment that
                      > features any JScript version earlier than 5.5 [which usually means IE5
                      > or earlier]), you should be prepared to emulate the call method:
                      >
                      > if(Function.pro totype
                      > && ('function' != typeof Function.protot ype.call))
                      > {
                      > Function.protot ype.call = function(o) {var p = '__call', r;
                      > while('undefine d' != typeof o[p]) {p += p;}
                      > o[p] = this; r = o[p](); delete o[p]; return r;
                      > };
                      > }
                      >
                      > If the object in question might be a host object (such as an element
                      > reference), remove the while statement and delete operator (otherwise
                      > IE will error) and don't use the same property name contained in the
                      > local variable, p.
                      >
                      > [snip]
                      >
                      > Hope that helps,
                      > Mike
                      >[/color]

                      Thanks!!!

                      Brett

                      Comment

                      Working...