0

Hey guys I'm having an issue with this statement in Internet Explorer, I was wondering if there is a saner way to do it?

var NEWVARIABLE = NEWVARIABLE || {};
NEWVARIABLE.Tools = NEWVARIABLE.Tools || {};

Its giving me the error that NEWVARIABLE does not exist

ehime
  • 8,025
  • 14
  • 51
  • 110

2 Answers2

3

You cannot use (or test) a variable that's not been defined. I originally thought that's what you were doing with the following statement

var NEWVARIABLE = NEWVARIABLE || {};

However, thanks to Fabrício, I realized that the var declaration gets hoisted (moved to the top of the script tag and is therefore already declared when it hits the statement.

The less confusing way to test if a variable is to use typeof === 'undefined' to see if a variable exists

var NEWVARIABLE;
if (typeof NEWVARIABLE === 'undefined') {
    NEWVARIABLE = {};
}

You can use the same style when checking for properties, you don't have to use typeof test for properties, you are allowed to test them even if they aren't defined.

RobG
  • 142,382
  • 31
  • 172
  • 209
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • 1
    if NEWVARIABLE is undefined, NEWVARIABLE is construct as a new object no ? – MyBoon Oct 08 '12 at 22:03
  • @My_Boon You are using it by running the if test, you're not allowed to try to read from an undefined variable – Ruan Mendes Oct 08 '12 at 22:04
  • AFAIK, in case the variable is not defined yet, `var` declarations are hoisted up to the top of the scope and have the native value `undefined` until the assignment is reached at runtime. Seems to work on this [fiddle](http://jsfiddle.net/9pMQJ/). – Fabrício Matté Oct 08 '12 at 22:05
  • Indeed, I've always makes like that – MyBoon Oct 08 '12 at 22:07
  • @FabrícioMatté But if there was already a NEWVARIABLE defined by a previous script, your code would overwrite it. – Ruan Mendes Oct 08 '12 at 22:07
  • Well that depends on the scope. If it is in the same scope, it'd be assigned to the same value. If it's an outer scope then yes, it'd overwrite it and your answer is a cleaner way of doing this. – Fabrício Matté Oct 08 '12 at 22:09
  • 1
    Here's commented [fiddle](http://jsfiddle.net/9pMQJ/5/), +1 for the extra cautiousness. – Fabrício Matté Oct 08 '12 at 22:13
  • Thanks for the lightening fast answer +1 @JuanMendes – ehime Oct 08 '12 at 22:19
  • @FabrícioMatté I would have expected the hoisted var statement to reset the variable to undefined, but it doesn't, so your comment makes a lot of sense. If the statement is in an innder scope, then you would have to use `window.NEWVARIABLE` anyway, I'm kind of confused... How is it that ehime is getting an error with his code, then? – Ruan Mendes Oct 08 '12 at 22:20
  • The `var` declaration just tells the interpreter that the variable to be used belongs to that scope, so a var declared more than once in the same scope doesn't make any difference at runtime. JSLint (Crockford) recommends moving all var declarations to the top of the scope they belong to, possibly to avoid such confusions. And yes, `window.NEWVARIABLE` and `window['NEWVARIABLE']` would allow you to access the global scope's as variable and functions declared in the global scope are added as properties of the `window` object as you stated. – Fabrício Matté Oct 08 '12 at 22:55
  • Now why it was returning an error on OP's code is beyond me, his question's code runs perfectly fine on IE9 - [fiddle](http://jsfiddle.net/TJERn/). Possibly due to the scoping. `=]` – Fabrício Matté Oct 08 '12 at 22:55
  • @FabrícioMatté Actually,it could be the same problem as http://stackoverflow.com/questions/4606847/why-does-ie-nuke-window-abc-variables/4607721#4607721 which I answered, that is, the variable may have been created using `window.MYVAR` and later on (in a different script tag, still at global scope), then a hoisted var statement actually overwrites `window.MYVAR`, only in IE. But maybe not, my example would still have the hoisted variable... – Ruan Mendes Oct 08 '12 at 23:07
  • Wow, JScript has way too many "peculiarities". I'll read it throughout. `=]` – Fabrício Matté Oct 08 '12 at 23:09
  • There is nothing wrong with the code in that it does not contain any syntax errors and should run without error in any ECMAScript compliant user agent. The answer marked as correct is misleading, NEWVARIABLE is defined and therefore able to be tested per the OP. Once an object reference is assigned by the first line, then properties can be tested too. Whatever was causing the OP's error, it wasn't this code. – RobG Oct 08 '12 at 23:11
  • @RobG Just to be accurate, my comments do explain that I don't think my solution is fixing the OP's problem (at least the way I thought it would) – Ruan Mendes Oct 08 '12 at 23:12
  • "**in any ECMAScript compliant user agent**", there is the problem, OP was asking specifically about IE. Juan's solution fixes it as per OP's feedback, so it's a correct answer IMO. – Fabrício Matté Oct 08 '12 at 23:26
  • But yes, @RobG has a point, the answer's first statement is misleading as the variable is in fact declared. – Fabrício Matté Oct 08 '12 at 23:30
  • @RobG and Fabrício, I've removed the erroneous statements from the answer, it's still a mistery how that solved the OP's problem. I wish the OP would show all the relevant code – Ruan Mendes Oct 08 '12 at 23:39
  • @FabrícioMatté—IE is about as ECMAScript compliant as any other browser (W3C DOM compliance is another matter, but getting better). It certainly has a few quirks (as do others) but they aren't relevant here. @Juan—did a minor edit to keep the JSLint-ophiles happy. :-) – RobG Oct 09 '12 at 00:42
  • Yes, IE is getting better as in, IE10 has about as many features and compliance as Firefox 4 had, problem is, XP users are stuck with IE8 and odds are IE10 won't even be ported to Win7, so not only Microsoft is always a couple years behind but also IE users tend to get stuck in time due to these quirks. But that's talk for another topic. `=]` – Fabrício Matté Oct 09 '12 at 00:46
0

You've accepted an answer, but it contains a misleading statement:

You cannot use (or test) a variable that's not been defined. That's what you're doing

The variable is declared, so it isn't what you are doing.

In the OP, the code:

> var NEWVARIABLE = NEWVARIABLE || {};
> NEWVARIABLE.Tools = NEWVARIABLE.Tools || {};

contains no syntax errors, the only case where it will throw an error is if NEWVARIABLE already exists and has a Tools property that throws an error when attempting to access or assign to it (as may happen with certain host objects).

If NEWVARIABLE has previously been assigned a native object or primitive value, it will not throw an error, though the result may not be what you expect.

RobG
  • 142,382
  • 31
  • 172
  • 209
  • @ehime I know that my answer did not address the question, but I don't see how this answers the question either. It just explains what was wrong with my question and doesn't suggest what the OP needs to do to solve it? ehime, what was your final solution? – Ruan Mendes Oct 15 '12 at 18:33
  • @JuanMendes—I was pointing out that there is insufficient information in the OP to provide a definitive answer, hence an explanation of why the error might occur as a hint as to what to look for in trying to fix it. – RobG Oct 15 '12 at 22:45
  • I understood what you did, I'm just trying to understand why the OP thinks this is the correct answer. – Ruan Mendes Oct 15 '12 at 22:59