Closed Bug 790418 Opened 12 years ago Closed 12 years ago

if blocks change function hoisting scope

Categories

(Core :: JavaScript Engine, defect)

15 Branch
x86_64
Windows 7
defect
Not set
normal

Tracking

()

RESOLVED DUPLICATE of bug 585536

People

(Reporter: charlesg, Unassigned)

Details

User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1

Steps to reproduce:

if you have a var declaration in an if block and a function declaration in a if block they are hoisted in order declared, so if the var declaration references the function it is not defined.

here are examples:
http://jsfiddle.net/xE2j2/   
vs   
http://jsfiddle.net/xE2j2/1/


Actual results:

function undefined.


Expected results:

function should of been hoisted before the var declaration.
Assignee: nobody → general
Component: Untriaged → JavaScript Engine
Product: Firefox → Core
Function declarations are not allowed in if blocks in JavaScript per spec; a fully spec-compliant ECMA-262 implementation would throw a SyntaxError on this syntax.  Different UAs implement different extensions to sort of make it work for web compat purposes.  I believe Spidermonkey treats this syntax:

  if (something) {
    function foo() {}
  }

as being equivalent to this (valid) syntax:

  if (something) {
    var foo = function foo() {}
  }

Which means that "foo" is undefined until the assignment expression is reached.

Other UAs do different (mutually incompatible) things with this syntax.

There is talk of extending the language to allow this syntax and define its semantics, but in the meantime it's probably best to avoid this construct.
Whiteboard: DUPEME
Cool info did not know that.  Thanks.
Status: UNCONFIRMED → RESOLVED
Closed: 12 years ago
Resolution: --- → INVALID
(In reply to Boris Zbarsky (:bz) from comment #1)
> I believe Spidermonkey treats this syntax:
> 
>   if (something) {
>     function foo() {}
>   }
> 
> as being equivalent to this (valid) syntax:
> 
>   if (something) {
>     var foo = function foo() {}
>   }
> 
> Which means that "foo" is undefined until the assignment expression is
> reached.

Oh no, that would be far too sane and regular.  In SpiderMonkey, block-level function statements *dynamically* add a name to the scope upon first execution (and re-assign to it on any subsequent execution).  Thus, any use of the name before the function statement has been executed will throw a ReferenceError (assuming the name isn't defined in an enclosing function or global scope).
yah it makes sense, but other browsers don't do it like this.

Lesson learned:  
1) Don't declare functions in if blocks at all because results will vary between browsers if you do. aka --> ("it's probably best to avoid this construct.")

Since browsers do not all handle it the same way, it's too risky to use, besides just being plain wrong. 

Personally i think it throwing an error anytime you do it would be better per spec, would make people notice your not suppose to do it quicker instead of getting them into the habit that you can do it.
Resolution: INVALID → DUPLICATE
Whiteboard: DUPEME
You need to log in before you can comment on or make changes to this bug.