Opera function visibility oddity

P

phil_gg04

Dear Javascript Experts,

Opera seems to have different ideas about the visibility of Javascript
functions than other browsers. For example, if I have this code:

if (1==2) {
function invisible() {
alert("invisible() called");
}
}

then most browsers will consider invisible() to be undefined. But in
Opera you can call it! You can try this online here:
http://chezphil.org/bugreps/funcdecl.html - with most browsers you'll
get an error (open your javascript console) but Opera will show the
alert.

So: is this an Opera bug, or is either behaviour acceptable? (I'd be
interested to know what Safari and any other less-common browsers do.)

--Phil.
 
R

Random

I wouldn't call this a bug-- it's why we can define functions at the
bottom of our script, or in the middle, or all over the place, and use
them anywhere. It's expected that function definitions using the
function statement will work regardless of where you put them. I've
actually had the same experience with IE (Win32).

If you really don't want that function defined except in certain
circumstances, try something like this:

if( foo )
bar = function ( arg1, arg2 ) {
// statements
}

Alternatively, you may use the Function constructor, but that can be
somewhat ponderous.
 
M

Michael Winter

On 24/05/2005 12:22, (e-mail address removed) wrote:

[snip]
if (1==2) {
function invisible() {
alert("invisible() called");
}
}

This is a syntax error. I imagine it is not flagged because it is
considered too common, and will break too many scripts. However, it is a
mistake and should never occur within a script.


There are three ways to create a function object in ECMAScript: the
function declaration, the function expression, and the Function
constructor function.

The first, the function declaration, is fairly simple and recognisable:

function <identifier> ( <argument list> ) {
<function body>
}

What is not always appreciated is that function declarations can only
appear in two general locations: at the program (aka root, or global)
level, and within the function body of another function. So,

/* Program */
function myFunction() {
}

and

/* Program */
function myOuterFunction() {

/* Function body */
function myInnerFunction() {
}

}

are fine. However,

if(condition) {

/* Statement list */
function myFunction() {
}

}

is not because statements like if and while expect other statements.

Function declarations are somewhat special. Unlike most source elements,
they are evaluated before execution would normally reach them. This is
why you can call a function before you have defined it.

When a script is initially parsed, all function declarations at the
program level will be evaluated, and the corresponding function objects
will be created. It is only after this process that execution begins.
Similarly, when a function is called, any inner function declarations
(such as myInnerFunction, above) are evaluated before execution of that
function commences.


The second, the function expression, is a little awkward to explain,
mainly because it might be difficult to see the distinction with
function declarations. Essentially, a function expression works like any
other expression: it is not evaluated until execution reaches it. This
allows you to create functions conditionally:

var func;

if(condition) {

func = function( <argument list> ) {
<function body>
};

}

Only if condition is true will the expression be evaluated. If condition
is false, func will remain undefined.

So, how /do/ you distinguish between a function expression and a
declarations? Essentially, it depends on the beginning of a source
element. If it starts with a 'function' token, it is a declaration. If
it starts with something else, it's a function expression. For example,

(function() {
/* ... */
})();

is a function expression because the source element begins with an
opening parenthesis.

A function expression can still have an identifier

func = function <identifier>( <argument list> ) {
<function body>
};

but this is only so the function can refer to itself - for recursion,
for example. It's not to be used outside of the function body.


I'll ignore the Function constructor for now. I'm sure the above is more
than enough information. What I will say is that although the Function
constructor can be used to create function objects at runtime like
function expressions, there are major differences between the two.

[snip]

If something needs more explanation, please ask.

Mike
 
H

Hallvord R. M. Steen

Opera seems to have different ideas about the visibility of Javascript
functions than other browsers. For example, if I have this code:

if (1==2) {
function invisible() {
alert("invisible() called");
}
}

then most browsers will consider invisible() to be undefined. But in
Opera you can call it!

This behaviour is by design.

If you want function definition to depend on an if clause, do the following

if (1==2) {
var invisible = function () {
alert("invisible() called");
}
}
 
P

phil_gg04

Mike Winter replied:
This is a syntax error
[snip lots of useful explanation]

Thanks Mike. I had just started to look it up in the Ecma
specification and was coming to the same conclusion.

I had come across this in the following context:

if (detect_some_browser) {
... declare functions for that browser ...
} else if (detect_some_other_browser) {
... declare function for that other browser ...
}

and it took a long time to understand why Opera was executing the
special IE versions of the functions, rather than the "all other
browser" ones.

Ideally, of course, all browsers would reject this with an error
message. I encourage Opera to either do what the other browsers do
(the pragmatic approach) or to reject it with an error message (the
purist approach). What they currently do, i.e. accept the invalid code
but interpret it differently from the other browsers, is confusing.

--Phil.
 
M

Michael Winter

On 24/05/2005 14:36, (e-mail address removed) wrote:

[snip]
if (detect_some_browser) {

Browser detection is flawed. Instead, you should be examining the
capabilities of any particular host. For example, Opera supports quite
of few of Microsoft's proprietary capabilities, as well as those defined
by the W3C.

See the browser detection entry in the group FAQ, and the related
article in the FAQ notes.

[snip]

Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top