1
if (!wysiwyg_toolbarButtons) {
    var wysiwyg_toolbarButtons = new Array(
        //command, display name, value, title, prompt/function, default text
        ["bold", "Strong", WYSIWYG_VALUE_NONE, "Give text strength"],
        ["italic", "Emphasis", WYSIWYG_VALUE_NONE, "Give text emphasis"],
        ["createlink", "Link", WYSIWYG_VALUE_PROMPT, "Create a hyperlink", "Enter the URL:", "http://"],
        ["unlink", "Unlink", WYSIWYG_VALUE_NONE, "Remove hyperlink"],
        ["insertimage", "Image", WYSIWYG_VALUE_PROMPT, "Insert an image", "Enter the URL of the image:", "http://"],
        ["inserthorizontalrule", "Rule", WYSIWYG_VALUE_NONE, "Insert horizontal rule"],
        ["div"], // place a toolbar divider
        ["formatblock", "Headling 1", "<H1>", "Make top level heading"],
        ["formatblock", "Headling 2", "<H2>", "Make 2nd level heading"],
        ["formatblock", "Headling 3", "<H3>", "Make 3rd level heading"],
        ["formatblock", "Paragraph", "<P>", "Make a paragraph"],
        ["formatblock", "Monospace", "<PRE>", "Make paragraph monospaced text"],
        ["insertunorderedlist", "List", null, "Make an unordered list"],
        ["insertorderedlist", "Ordered List", null, "Make an ordered list"],
        ["div"], // place a toolbar divider
        ["toggleview", "Source", "Compose", "Switch views"]
    );
}

It's from this file,with a demo here

My problem is:why doesn't it report "ReferenceError: wysiwyg_toolbarButtons is not defined"?

user198729
  • 61,774
  • 108
  • 250
  • 348

5 Answers5

5

JavaScript in the web browser searches attributes in the window object. Accessing an unknown attribute does not throw an error, so in fact it is evaluated as something like this:

if( !window.wysiwyg_toolbarButtons ) { }

Try if( !wtf ) { alert('error'); } and if( !window.wtf ) { alert('no error'); } in the Firebug Console.

EDIT

Currently the console in firebug evals the code using with( window ) { ..console..code.. }. But the "with" statement is tricky, example:

>>> alert(location);
= eval( "with( window ) { alert(location); }" );
OK, "location" attribute found in window

>>> alert(wtf);
= eval( "with( window ) { alert(wtf); }" );
ERROR, "wtf" not found in window, and not in global scope, throws ReferenceError

The implicit window object in the browser behaves differently than as it would be used with the "with" statement.

Frunsi
  • 7,099
  • 5
  • 36
  • 42
  • ah! makes sense then with regards to the behavior I see when testing with Rhino. +1 – jldupont Dec 11 '09 at 02:47
  • But when I type `location`,firebug gives the result of window.location correctly – user198729 Dec 11 '09 at 02:50
  • 1
    Yes, seems to be a bug - or lets say subtlety - in firebug. I guess firebug searches the "window scope" manually for an attribute that matches, and falls back to throw the exception if no match was found. – Frunsi Dec 11 '09 at 02:54
  • 2
    The "bug" is because Firebug executes the input wrapped in a _with_ statement: `with( window } { ..console..code.. }`. Also see http://stackoverflow.com/questions/61552/are-there-legitimate-uses-for-javascripts-with-statement – Frunsi Dec 11 '09 at 03:13
  • firebug issue tracker (somewhere there.. lost the url), and source code: http://code.google.com/p/fbug/source/browse/branches/firebug1.5/content/firebug/commandLine.js#242 – Frunsi Dec 11 '09 at 04:17
2

The first thing the code does is a truthiness evaluation of wysiwyg_toolbarButtons, since it evaluates to false being undefined then the block enters and the variable is defined.

Quintin Robinson
  • 81,193
  • 14
  • 123
  • 132
  • 1
    But when I type `if(!nosuchvariable)alert(1);` in firebug,it just reports a error – user198729 Dec 11 '09 at 02:30
  • Truthiness is a bit of a funny word, but he means something like "truth-value test", i.e., does `wysiwyg_toolbarButtons` evaluate to true or false? `undefined` is also considered `false`. – mpen Dec 11 '09 at 02:31
  • Truthy is fairly common terminology for javascript (at least in my world)... "such values can be called "truthy" and "falsy," respectively." - From "A re-introduction to JavaScript" by Simon Willison. – Quintin Robinson Dec 11 '09 at 02:33
  • @unknown (google) - Are you just trying to execute code directly inline with firebug? – Quintin Robinson Dec 11 '09 at 02:34
  • I believe the reason this is happening is because the script cannot evaluate that the variable in question will ever be defined. Try `if(!nosuchvariable){var nosuchvariable=1; alert(nosuchvariable);}`.. does that work at all? – Quintin Robinson Dec 11 '09 at 02:47
1

What that code is doing is checking if wysiwyg_toolbarButtons is defined, and if it is not, it's defining and initializing it.

Andreas Grech
  • 105,982
  • 98
  • 297
  • 360
-1

Javascript is not block scoped so the var declaration inside the if is just the same as if it had happened before the if.

Adam Hupp
  • 1,513
  • 8
  • 7
-2

EDIT: Yep, I misunderstood what I was saying. Sorry for the bad answer.

Based on your code, wysiwyg_toolbarButtons is created local to the if statement. The var declaration tells JavaScript that this is a new variable, and anything inside of the if statement's scope will use this new variable.

I'm assuming this code is functioning with the statements like that. Whether or not it successfully changes wysiwyg_toolbarButtons (or wysiwyg_elementMap, as I scan the JS file) outside of that scope doesn't matter. Keeping the declaration like that is bad coding practice, because it won't work like that in other languages.

Otherwise, I'm not going to restate what Quintin, Andreas, and Dimitar already said.

Jeff Rupert
  • 4,690
  • 2
  • 20
  • 17
  • 1
    It doesn't seem that an `if` statement creates a "scope". I tried a simple test in Rhino and a variable (e.g. `var hi=rue`) declared inside an `if` is visible outside. – jldupont Dec 11 '09 at 02:44
  • Right, but I made my point more because it's a smart programming practice and something that could _potentially_ be dangerous to other languages. If I understand correctly, the only reason it works like that is because browsers conformed to the poor practices of the scripters instead of forcing them to learn good practices. Also, because of how JavaScript actually houses its variables, it would make sense that the scope doesn't work exactly how it should. It's unimportant if you'll never code in any other language or never reuse a variable name, I suppose. – Jeff Rupert Dec 11 '09 at 02:47
  • @Jeff: javascript scope is tricky, but a lot of code depends on how it works (e.g. javascript "namespaces"). It has nothing to do with browsers implementations. Its supposed to be like it is, its standard. This example is NO bad practice, its fine. – Frunsi Dec 11 '09 at 02:50
  • @Jeff: "If I understand correctly, the only reason it works like that is because browsers conformed to the poor practices of the scripters instead of forcing them to learn good practices." No, it works like that by design. Blocks in JavaScript don't introduce new scopes, only functions do. This is a feature, not a bug. Also, I don't really see how coding like that is bad practice just because "it won't work like that in other languages." By that logic, prototypical inheritance should be avoided since it doesn't work in (most) other languages either. – bcat Dec 11 '09 at 02:57
  • Well, this was an ignorant answer for me to have made. Thanks jldupont for catching my error, and frunsi and bcat for better explaining why I was wrong. – Jeff Rupert Dec 11 '09 at 03:20