views:

186

answers:

5

Hello!

<div id="myElement1"></div>
<div id="myElement2"></div>

<script>
window.onload = function() {
    document.getElementById("myElement1").onclick = function() {
        for (i = 0; i < 2; i++) {
            document.getElementById("myElement2").onmouseover = func;
            function func() {alert("hello"); } } } }
</script>

In chrome and IE, when myElement1 is clicked, func is attached perfectly to myElement2. However, in firefox when myElement1 is clicked I receive an error message stating that func is not defined.

I should note that if make an anonymous function instead of func then it works in all 3 browsers.

My question is how does firefox handle scope in this regard differently to IE and chrome?

Will.

+3  A: 

I think the issue is that func is being defined inside a block. Try running your code through JSLint and you'll notice the following issues:

  • Function statements cannot be placed in blocks. Use a function expression or move the statement to the top of the outer function.
  • 'func' was used before it was defined.

Try assigning a function expression instead of defining a function and assigning it by name, perhaps like this:

document.getElementById("myElement2").onmouseover = function() {
    alert("hello")
};
Jimmy Cuadra
Thank you for telling me about JSLint.
willat8
Don't take everything JSLint says as gospel. But yeah, function statements can't go in if/for/etc. blocks according to the ECMAScript standard. Browsers currently let it slide, but the behaviour you get when you do it will vary. Avoid.
bobince
+1  A: 

try this:

<script>
window.onload = function() {
    document.getElementById("myElement1").onclick = function() {
        for (i = 0; i < 2; i++) {
            var func = function() {alert("hello");} 
            document.getElementById("myElement2").onmouseover = func;
        } 
    }
}
</script>
John Boker
+1  A: 

I would recommend moving the declaration in front of the assignment, and using a variable to hold the function instead of declaring it globally:

<script>
window.onload = function() {
    document.getElementById("myElement1").onclick = function() {
        for (i = 0; i < 2; i++) {
            var func = function() { alert("hello"); }
            document.getElementById("myElement2").onmouseover = func;
        }
    } 
}
</script>
Doug Neiner
Thank you, I shall do this.
willat8
+1  A: 

You have a scope problem because your function definition is within a function. I usually encapsulate functions in an object. You probably don't need the loop too.

Take a look:

<div id="myElement1"></div>
<div id="myElement2"></div>
<script type="text/javascript">

    window.onload = function() {
        document.getElementById("myElement1").onclick = function() {
                document.getElementById("myElement2").onmouseover = myFunctions.func;
         }
     }
    /* Function definitions */ 
    var myFunctions = new Object();
    myFunctions.func = function () {
       alert("hello"); 
    }
</script>
JONYC
That would be a good idea except I have a lot of little functions which I want to define in the places where they will be used.
willat8
I know it's convenient for you . But defining functions on the fly is not best practice. If you do a var func within an onclick, there is no way to reference that thus creating a memory hole. As best practice, you should bind your functions somewhere and when need be, you can deconstruct it by setting it to null.Something to think about when you venture into more Front-end programming. :)
JONYC
Ah I see why you would use the object idea. Fortunately the vast, vast majority of all the little functions I am defining remove themselves from the event listener list after execution. Do I still get memory holes doing this?
willat8
When you say "little" functions, what are you doing? I've never come to a situation where I have to define arbitrary functions in JS and abandon them.If you REALLY have to do it, set them all to null at the end of the operation like this:var func = function() { alert("hello"); }document.getElementById("myElement2").onmouseover = func;func = null;
JONYC
Thank you for the advice. I'm trying to emulate a desktop system and 'am currently focusing on icon dragging. I never thought I would have to write as much code as this feature alone is requiring, but it's mainly to teach myself the language through Doing so I think it's more than worthwhile.
willat8
A: 

As for "how does firefox handle scope in this regard differently to IE and chrome?" - see http://yura.thinkweb2.com/named-function-expressions/#function-statements

Nickolay
Looks like a brilliant page, I've bookmarked it for later reading. Thanks a lot.
willat8