SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    Quick question on how functions work

    Hi. I have two questions that are really bugging me and I don't seem to be able to find an answer to them.

    1. I have the following that does things when a key is pressed:
    Code:
          var doPrev = swap(prev);
          var doNext = swap(next);
          document.onkeydown = function(e) {
            if (e == null) {keycode = event.keyCode;}
            else {keycode = e.which}
            switch(keycode) {
            case 190:
              document.onkeydown = null;
              doNext();
              break;
            case 188:
              document.onkeydown = null;
              doPrev();
              break;
            }
          }
    However, if I change it to this, it no longer works (swap(arg) is not run):
    Code:
          document.onkeydown = function(e) {
            if (e == null) {keycode = event.keyCode;}
            else {keycode = e.which}
            switch(keycode) {
            case 190:
              document.onkeydown = null;
              swap(next);
              break;
            case 188:
              document.onkeydown = null;
              swap(prev);
              break;
            }
          }
    Why is this?

    2. I know that when an event occurs, the element it happened on is passed as the first argument (but not in IE), so this sort of thing is done:
    Code:
    something.onclick = doit;
    
    function doit(e) {
      if (!e) var e = window.event;
      var t = (window.event) ? e.srcElement : e.target;
      // do things with t
    }
    But what if when I call doit I want to pass something as an argument? I tried the following but it doesn't work:
    Code:
    something.onclick = doit(someVar);
    
    function doit(e, someVar) {
      if (!e) var e = window.event;
      var t = (window.event) ? e.srcElement : e.target;
      // do things with t and someVar
    }
    Can this be done? Thanks in advance,

    Rafael

  2. #2
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,604
    Mentioned
    24 Post(s)
    Tagged
    1 Thread(s)
    When you run:

    var doPrev = swap(prev);
    var doNext = swap(next);

    The values returned from those function calls are returned and set as the action to perform when the doPrev() and doNext() functions are called. The values returned are the code to be run in those instances.

    If instead you run the original functions inside the event handler then:

    1. The functions to be run are returned but never run
    2. The values in prev and next may have changes and so the functions returned that you are not running may not be the functions that you intended to run anyway.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  3. #3
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Thanks felgall, that clears it up for me.

    As for the second question, I'm pretty sure now that it's impossible, since it has to be something.onclick = function; rather than something.onclick = function(); for 'e' to be passed on.

    I just use global variables instead. Is this bad/good practice at all?

  4. #4
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You need to understand: a)what the function execution operator is, b) what it does, and c) what happens as a result.

    a) The function execution operator is: ()

    b) The function execution operator causes the function to execute--except when it appears in the function header of a function definition e.g.:
    Code:
    function someFunc()
    {
         alert("hello");
    }
    In that case, the function is not executed. However, if you write:

    someFunc();

    The function execution operator causes the function to execute.

    c) The result of executing a function is: the function call in the javascript code is replaced by the function's return value. For instance if you have a function:
    Code:
    function someFunc()
    {
         return "hello world";
    }
    and you write:

    var someVar = doit();

    js converts that statement to:

    var someVar = "hello world";

    If the function doesn't have a return statement, then the return value is the value undefined.

    But, what happens if you write:

    var f = someFunc;

    No execution operator is present in that statement, so no function executes. What does that do? It says, "Mr. JS, I would like to create a nickname for the function I originally named someFunc. The nickname I want to use is 'f'. From now on please take note that when I refer to 'f' in my code, I am talking about 'someFunc'. Writing that statement in your code allows you to subsequently write lines like:

    f();

    and then someFunc will execute--because 'f' is a nickname for someFunc.

    Now lets look at your numbered questions:

    1) Suppose swap() is defined like this:
    Code:
    function swap(arg)
    {
        alert(arg);
    }
    Then you write:

    swap(10);
    //Error ridden code here

    and conclude swap() works because 10 is alerted.

    Then suppose you write:

    //error ridden code here
    swap(10);

    and conclude swap() doesn't work. Why doesn't swap work? Because execution of the script was halted due to errors before swap() could ever execute. There's nothing wrong with swap() in the latter case--it was just placed after some code that halted execution of the script.

    2)
    so this sort of thing is done:
    something.onclick = doit();
    Generally, that sort of thing is never done. Since the function execution operator is present, it causes doit() to execute, and then the return value of doit() is substituted into that line:

    something.onclick = <return value of doit()>;

    If doit() returns the string "hello world". Then that statement will be converted to:

    something.onclick = "hello world";

    After that assignment, something.onclick will be a nickname for the string "hello world". But that isn't the only consequence of that statement. That statement also tells js to do something when a user clicks on the 'something' html element. Thereafter, if a user clicks on the 'something' html element, js does this:

    something.onclick()

    Since something.onclick is a nickname for the string "hello world", that statement is the same as:

    "hello world"()

    However, that is nonsensical. A string is not a function, and therefore it can't be executed, so that produces an error.

    It is possible to write a statement like:

    something.onclick = doit();

    and not have it produce an error when the user clicks on the something element. No error would occur if doit() returned a function:
    Code:
    function myFunc()
    {
         alert("goodbye");
    }
    
    function doit()
    {
         return myFunc;
    }
    With those definitions, the line:

    something.onclick = doit();

    produces:

    something.onclick = myFunc;

    and thereafter something.onclick becomes a nickname for myFunc. As before, if someone clicks on the something element, js does this:

    something.onclick();

    which is equivalent to:

    myFunc();

    Since myFunc is a function, you can legally apply the function execution operator to it, and therefore no error will occur.
    But what if when I call doit() I want to pass something as an argument? I tried the following but it doesn't work:

    something.onclick = doit(someVar);
    That says you want to make something.onclick the nickname for doit(someVar)'s return value. Unless the return value is a function, you will get an error when js does this:

    something.onclick();
    How is it done?
    Like this:

    something.onclick = function(e){ doit(e, someVar) };

    That says, "Mr. JS from now on I want to use something.onclick as the nickname for the particular unamed function that I am defining on the right side of this assignment operator." Thereafter, when js does this:

    something.onclick()

    that will execute the code in the body of the unnamed function. What code is in the body? A function call to doit() that takes the e parameter that the unamed function receives from js and passes it on to doit() along with another parameter.

    As far as that other parameter "someVar", it's not always the case that when the function executes it will be able to read someVar's current value. That's because someVar has some value now, but the function is going to execute at some time in the future, i.e. when the user clicks on the element. The current value of someVar may not be the value that js sees for someVar's value in the future. The issues have to do with what are called "closures", and closures are the Bermuda Triangle of javascript: unless you know what you are doing, strange things can happen.
    Last edited by 7stud; Feb 18, 2007 at 19:55.

  5. #5
    SitePoint Guru
    Join Date
    Apr 2006
    Posts
    802
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    something.onclick=function(e){
    e= e || window.event;
    var whozit= e.srcElement || e.target;
    // do whatever you need with whozit and e
    }
    Last edited by mrhoo; Feb 20, 2007 at 10:10.

  6. #6
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    7stud, thanks so much for that detailed explanation. After reading other people's code and faffing about with my own and reading the odd blog/spec/tutorial, and now this, it's all fallen into place.

    Cheers mrhoo, using an anonymous function makes it much easier.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •