Using eval() for function definition

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

    Using eval() for function definition

    Hello,

    I have this particular problem with eval() when using Microsoft
    Internet Explorer, when trying to define an event handler. This is the
    code:

    function BigObject()
    {
    this.items = new Array();
    this.values = new Array();

    this.addItem = function( item )
    {
    this.items[this.items.leng th] = item;
    }

    this.makeHandle rs()
    {
    var i, length = this.items.leng th;
    for ( i = 0; i < length; i++ )
    this.items[i].onclick = function()
    { alert( this.values[i] ); };
    }
    }

    However, this last code (makeHandlers() method) doesn't work since the
    expression "this.value s[i]" automatically belongs to this new
    anonymous function, and therefore isn't valid (since the new anonymous
    function(s) don't have the "values" attribute. So I tried the
    following:
    this.items[i].onclick = eval( "function() { alert( " +
    this.values[i] + "); }" );
    and it worked! ... in Firefox only :( Internet explorer returns
    "undefined" for eval( "function() { /* whatever */ ); } " ), for the
    same things Firefox perfectly understands, and if I try to make it a
    handler, an exception is fired in IE. What do I do? Did I come to the
    right conclusion with IE or am I making a banal mistake? Do I need to
    find another way of solving this or is there a fix to this solution?

    Thank you,
    Darko

  • Darko

    #2
    Re: Using eval() for function definition

    On Feb 19, 4:56 pm, "Darko" <darko.maksimo. ..@gmail.comwro te:
    Hello,
    >
    I have this particular problem with eval() when using Microsoft
    Internet Explorer, when trying to define an event handler. This is the
    code:
    >
    function BigObject()
    {
    this.items = new Array();
    this.values = new Array();
    >
    this.addItem = function( item )
    {
    this.items[this.items.leng th] = item;
    }
    >
    this.makeHandle rs()
    {
    var i, length = this.items.leng th;
    for ( i = 0; i < length; i++ )
    this.items[i].onclick = function()
    { alert( this.values[i] ); };
    }
    >
    }
    >
    However, this last code (makeHandlers() method) doesn't work since the
    expression "this.value s[i]" automatically belongs to this new
    anonymous function, and therefore isn't valid (since the new anonymous
    function(s) don't have the "values" attribute. So I tried the
    following:
    this.items[i].onclick = eval( "function() { alert( " +
    this.values[i] + "); }" );
    and it worked! ... in Firefox only :( Internet explorer returns
    "undefined" for eval( "function() { /* whatever */ ); } " ), for the
    same things Firefox perfectly understands, and if I try to make it a
    handler, an exception is fired in IE. What do I do? Did I come to the
    right conclusion with IE or am I making a banal mistake? Do I need to
    find another way of solving this or is there a fix to this solution?
    >
    Thank you,
    Darko
    I'm sorry, I had a syntax error in the post I submitted, just in case
    someone thinks that is the reason for my troubles, it isn't - it was a
    typo just in the post here:
    this.makeHandle rs()
    { ...
    should have been written:
    this.makeHandle rs = function()
    { ...

    Comment

    • Geoffrey Summerhayes

      #3
      Re: Using eval() for function definition

      On Feb 19, 10:56 am, "Darko" <darko.maksimo. ..@gmail.comwro te:
      Hello,
      >
      I have this particular problem with eval() when using Microsoft
      Internet Explorer, when trying to define an event handler. This is the
      code:
      >
      function BigObject()
      {
      this.items = new Array();
      this.values = new Array();
      >
      this.addItem = function( item )
      {
      this.items[this.items.leng th] = item;
      }
      >
      this.makeHandle rs()
      {
      var i, length = this.items.leng th;
      for ( i = 0; i < length; i++ )
      this.items[i].onclick = function()
      { alert( this.values[i] ); };
      }
      >
      }
      >
      Same thing happens in Lisp:
      CL-USER: (let ((foo #1A(1 2 3)))
      (funcall (car (loop for i below 3 collect (lambda() (aref
      foo i))))))

      Error: The subscript 3 exceeds the limit 2 for the first dimension
      of the array #(1 2 3).
      1 (abort) Return to level 0.
      2 Return to top loop level 0.

      You're not creating the closure you think you are,
      it is binding on i. What you are getting is

      function(){aler t(this.values[length]);}

      for all of them because i=length at the end of
      the loop.

      Try this, create a function

      function foo(x){return function(){aler t(x)}}

      and use

      this.items[i].onclick=foo(th is.values[i]);


      ---
      Geoff

      Comment

      • Darko

        #4
        Re: Using eval() for function definition

        On Feb 19, 8:18 pm, "Geoffrey Summerhayes" <sumr...@hotmai l.com>
        wrote:
        On Feb 19, 10:56 am, "Darko" <darko.maksimo. ..@gmail.comwro te:
        >
        >
        >
        Hello,
        >
        I have this particular problem with eval() when using Microsoft
        Internet Explorer, when trying to define an event handler. This is the
        code:
        >
        function BigObject()
        {
        this.items = new Array();
        this.values = new Array();
        >
        this.addItem = function( item )
        {
        this.items[this.items.leng th] = item;
        }
        >
        this.makeHandle rs()
        {
        var i, length = this.items.leng th;
        for ( i = 0; i < length; i++ )
        this.items[i].onclick = function()
        { alert( this.values[i] ); };
        }
        >
        }
        >
        Same thing happens in Lisp:
        CL-USER: (let ((foo #1A(1 2 3)))
        (funcall (car (loop for i below 3 collect (lambda() (aref
        foo i))))))
        >
        Error: The subscript 3 exceeds the limit 2 for the first dimension
        of the array #(1 2 3).
        1 (abort) Return to level 0.
        2 Return to top loop level 0.
        >
        You're not creating the closure you think you are,
        it is binding on i. What you are getting is
        >
        function(){aler t(this.values[length]);}
        >
        for all of them because i=length at the end of
        the loop.
        >
        Try this, create a function
        >
        function foo(x){return function(){aler t(x)}}
        >
        and use
        >
        this.items[i].onclick=foo(th is.values[i]);
        >
        ---
        Geoff
        It actually worked! Thank you a lot! I thought about a similar way,
        creating a function object that would receive arguments, and generated
        a function, but the way I did it couldn't help neither. This is
        perfect, thank you!

        Darko

        Comment

        • David Golightly

          #5
          Re: Using eval() for function definition

          On Feb 19, 8:14 am, "Darko" <darko.maksimo. ..@gmail.comwro te:
          On Feb 19, 4:56 pm, "Darko" <darko.maksimo. ..@gmail.comwro te:
          >
          >
          >
          Hello,
          >
          I have this particular problem with eval() when using Microsoft
          Internet Explorer, when trying to define an event handler. This is the
          code:
          >
          function BigObject()
          {
          this.items = new Array();
          this.values = new Array();
          >
          this.addItem = function( item )
          {
          this.items[this.items.leng th] = item;
          }
          >
          this.makeHandle rs()
          {
          var i, length = this.items.leng th;
          for ( i = 0; i < length; i++ )
          this.items[i].onclick = function()
          { alert( this.values[i] ); };
          }
          >
          }
          >
          However, this last code (makeHandlers() method) doesn't work since the
          expression "this.value s[i]" automatically belongs to this new
          anonymous function, and therefore isn't valid (since the new anonymous
          function(s) don't have the "values" attribute. So I tried the
          following:
          this.items[i].onclick = eval( "function() { alert( " +
          this.values[i] + "); }" );
          and it worked! ... in Firefox only :( Internet explorer returns
          "undefined" for eval( "function() { /* whatever */ ); } " ), for the
          same things Firefox perfectly understands, and if I try to make it a
          handler, an exception is fired in IE. What do I do? Did I come to the
          right conclusion with IE or am I making a banal mistake? Do I need to
          find another way of solving this or is there a fix to this solution?
          >
          Thank you,
          Darko
          >
          I'm sorry, I had a syntax error in the post I submitted, just in case
          someone thinks that is the reason for my troubles, it isn't - it was a
          typo just in the post here:
          this.makeHandle rs()
          { ...
          should have been written:
          this.makeHandle rs = function()
          { ...
          First off: using "eval" in this context is completely inappropriate.
          For one thing, you have the "Function" constructor which works in much
          the same way; for another, a proper understanding of closures will
          help to avoid this problem.

          You have inadvertently touched on one of the more advanced topics in
          JavaScript: closures and "this" keyword resolution. Understanding
          this is key to using mature JavaScript technique. Please read this
          article:

          http://www.jibbering.com/faq/faq_notes/closures.html (by this list's
          own Richard Cornford)

          and then come back if you still have questions.

          -David

          Comment

          • Richard Cornford

            #6
            Re: Using eval() for function definition

            Darko wrote:
            I have this particular problem with eval() when using
            Microsoft Internet Explorer, when trying to define an
            event handler. This is the code:
            >
            function BigObject()
            {
            this.items = new Array();
            this.values = new Array();
            >
            this.addItem = function( item )
            {
            this.items[this.items.leng th] = item;
            }
            This - addItem - method does not take advantage of its status as an inner
            function (its unique identify and the closure resulting form its
            assignment). Under those circumstances it would be better to assign it to
            the - BigObject.proto ype - so a single function object may be shared as
            an instance method of all - BigObject - instances.
            this.makeHandle rs()
            Noting the correction; this.makeHandle rs = function()
            {
            var i, length = this.items.leng th;
            for ( i = 0; i < length; i++ )
            this.items[i].onclick = function()
            { alert( this.values[i] ); };
            In javascript the value of the - this - keyword is determined by how a
            function is called. It is not a property of the function objects
            themselves. In response to events, a browser calls the functions assigned
            to its intrinsic event properties as methods of the DOM Element to which
            the handler is assigned, this leaves the - this - keyword referring to
            the DOM Element.
            }
            This method makes no use of its status as an inner function and so should
            again be assigned to the prototype.
            }
            >
            However, this last code (makeHandlers() method) doesn't work
            since the expression "this.value s[i]" automatically belongs
            to this new anonymous function,
            No, it doesn't work because - this - refers to the DOM Element and the -
            i - value belongs to the one containing execution and has the value it
            had when the - for - loop finished.
            and therefore isn't valid (since the new anonymous
            function(s) don't have the "values" attribute.
            They don't, but it is the DOM Element not having a - values - property
            that is significant here.
            So I tried the following:
            this.items[i].onclick = eval( "function() { alert( " +
            this.values[i] + "); }" );
            and it worked!
            It would be more accurate to say that where it 'worked' it actually
            failed to fail as expected. The - eval - function executes its string
            argument as a complete javascript Program, and the units that a Program
            can be made up of are Statements and FunctionDeclara tions. A
            FunctionDeclara tion must have an Identifier as the function name, so your
            string is not a syntactically correct FunctionDeclara tion. A statement
            may not start with the - function - keyword, so your string is not a
            syntactically correct Statement, and so it also cannot be a syntactically
            correct javascript Program.

            A combination of using - eval - (which often acts to mask errors, or make
            them indirect/obscure) , syntax extensions and error tolerance
            (particularly in IE's case) may conspire to give the impression of
            something that 'works', but there is nothing in the language to suggest
            that this would ever be effective code to be writing.
            ... in Firefox only :( Internet explorer returns
            "undefined" for eval( "function() { /* whatever */ ); } " ),
            for the same things Firefox perfectly understands, and if I
            try to make it a handler, an exception is fired in IE.
            You are not allowed to assign the undefined value to an intrinsic event
            property in IE.
            What do I do?
            <snip>

            First, learning javascript's syntax might be of some use while attempting
            to write it.

            You need to have a function that is called as a method of a DOM element
            reference a property of a particular javascript object instance, and
            employ an individual and unique index with that property. The following
            will do that, but you will have to look at the URL reference to
            understand why:-

            function BigObject(){
            this.items = new Array();
            this.values = new Array();
            }
            BigObject.proto type.addItem = function(item){
            this.items[this.items.leng th] = item;
            };
            BigObject.proto type.makeHandle rs = function(){
            var i, length = this.items.leng th;
            var self = this; // Make the object instance available on the scope
            // chain as a - self - variable.
            for ( i = 0; i < length; i++ ){
            this.items[i].onclick = (function(index ){
            return (function(){
            alert( self.values[index] ); // self - is resolved
            // against the scope
            // chain, and resolves as
            // a reference to the
            // individual javascript
            // object instance
            // assigned in the
            // outermost function with
            // the - this - keyword.
            });
            })(i); // Pass the individual index - i - as an argument to the
            // function call that returns the event handling
            // function. This allows the event handling function to
            // reference its index as the outer unction's - index -
            // formal parameter.
            }
            };


            See:-
            <URL: http://jibbering.com/faq/faq_notes/closures.html >

            Richard.

            Comment

            • Darko

              #7
              Re: Using eval() for function definition

              On Feb 19, 10:31 pm, "Richard Cornford" <Rich...@litote s.demon.co.uk>
              wrote:
              Darko wrote:
              I have this particular problem with eval() when using
              Microsoft Internet Explorer, when trying to define an
              event handler. This is the code:
              >
              function BigObject()
              {
              this.items = new Array();
              this.values = new Array();
              >
              this.addItem = function( item )
              {
              this.items[this.items.leng th] = item;
              }
              >
              This - addItem - method does not take advantage of its status as an inner
              function (its unique identify and the closure resulting form its
              assignment). Under those circumstances it would be better to assign it to
              the - BigObject.proto ype - so a single function object may be shared as
              an instance method of all - BigObject - instances.
              The other day I saw in some script the prototype thing, I didn't
              really understand what it was for, now I understand a little better,
              and the links you gave to me seem to contain more about the issue;
              I'll have to give it a closer look. Anyway, sounds like a good idea to
              share the function definition among all the function-objects.
              >
              this.makeHandle rs()
              >
              Noting the correction; this.makeHandle rs = function()
              >
              {
              var i, length = this.items.leng th;
              for ( i = 0; i < length; i++ )
              this.items[i].onclick = function()
              { alert( this.values[i] ); };
              >
              In javascript the value of the - this - keyword is determined by how a
              function is called. It is not a property of the function objects
              themselves. In response to events, a browser calls the functions assigned
              to its intrinsic event properties as methods of the DOM Element to which
              the handler is assigned, this leaves the - this - keyword referring to
              the DOM Element.
              How stupid of me. Of course it's the element the event is about that
              the "this" attribute is of, I have already been using it, just didn't
              recognise the relation, I completely lost it.
              This method makes no use of its status as an inner function and so should
              again be assigned to the prototype.
              >
              }
              So I tried the following:
              this.items[i].onclick = eval( "function() { alert( " +
              this.values[i] + "); }" );
              and it worked!
              >
              It would be more accurate to say that where it 'worked' it actually
              failed to fail as expected. The - eval - function executes its string
              argument as a complete javascript Program, and the units that a Program
              can be made up of are Statements and FunctionDeclara tions. A
              FunctionDeclara tion must have an Identifier as the function name, so your
              string is not a syntactically correct FunctionDeclara tion. A statement
              may not start with the - function - keyword, so your string is not a
              syntactically correct Statement, and so it also cannot be a syntactically
              correct javascript Program.
              I don't quite understand what you mean when you say a statement may
              not start with the function keyword? How is that? How about function
              definitions?
              First, learning javascript's syntax might be of some use while attempting
              to write it.
              Yes, well, I have learnt the 'var' and 'if' keywords, and something
              about semicolons, I thought that might do it? ;-)
              function BigObject(){
              this.items = new Array();
              this.values = new Array();}
              >
              BigObject.proto type.addItem = function(item){
              this.items[this.items.leng th] = item;};
              >
              BigObject.proto type.makeHandle rs = function(){
              var i, length = this.items.leng th;
              var self = this; // Make the object instance available on the scope
              // chain as a - self - variable.
              for ( i = 0; i < length; i++ ){
              this.items[i].onclick = (function(index ){
              return (function(){
              alert( self.values[index] ); // self - is resolved
              // against the scope
              // chain, and resolves as
              // a reference to the
              // individual javascript
              // object instance
              // assigned in the
              // outermost function with
              // the - this - keyword.
              });
              })(i); // Pass the individual index - i - as an argument to the
              // function call that returns the event handling
              // function. This allows the event handling function to
              // reference its index as the outer unction's - index -
              // formal parameter.
              }
              };
              Why, thank you a lot! This code was easily conceivable, with the
              comments of course, and I took a look in that text, it's bookmarked
              all right :) Thanks to you once again!

              Comment

              • Richard Cornford

                #8
                Re: Using eval() for function definition

                On Feb 20, 2:23 pm, Darko wrote:
                On Feb 19, 10:31 pm, Richard Cornford wrote:
                >Darko wrote:
                <snip>
                >>and it worked!
                >
                >It would be more accurate to say that where it 'worked' it actually
                >failed to fail as expected. The - eval - function executes its string
                >argument as a complete javascript Program, and the units that a
                >Program can be made up of are Statements and FunctionDeclara tions.
                >A FunctionDeclara tion must have an Identifier as the function name,
                >so your string is not a syntactically correct FunctionDeclara tion. A
                >statement may not start with the - function - keyword, so your string
                >is not a syntactically correct Statement, and so it also cannot be a
                >syntacticall y correct javascript Program.
                >
                I don't quite understand what you mean when you say a statement may
                not start with the function keyword? How is that? How about function
                definitions?
                <snip>

                The units of a javascript program are FunctionDeclara tions and
                Statements. What you are calling a function definition would be the
                structure that qualifies as a Function Declaration, and so _not_ a
                Statement. The only form of statement that could commence with the -
                function - keyword is an ExpressionState ment, and the syntax rules for
                the ExpressionState ment explicitly forbid it from commencing with an
                opening brace ("{") or the - function - keyword. This is probably to
                avoid the result being ambiguous (making it clear that an
                ExpressionState ment is not either a Function Declaration or an object
                literal).

                Richard.

                Comment

                Working...