12

I am checking if a variable is defined or not, and if it is not defined explicitly I am going to define it by doing:

if ( typeof(aVariable) == 'undefined' ) {
  var aVariable = value;
}

Because the variable is not defined JSLint warns that it is used before it is defined, and that is exactly what I want.

How can I overcome this?

I want to enable defining those variables explicitly doing this:

<script>
  var aVariable = value;
</script>
<script src="myScript.js"></script>

So everyone who is going to include this script can customize some of the properties. And I am afraid I cannot change this logic because it is already being used in hundred of web sites this way.

Scroll down for the answers/solutions, because I have answered my own question Stack Overflow does not show it up. Be sure not to miss them.

nimcap
  • 10,062
  • 15
  • 61
  • 69

6 Answers6

7

I think what JSLint is telling you is that you shouldn't use variables before they are defined. If you are happy that it is appropriate in your scenario - you can ignore that warning. If you aren't absolutely sure, have another think about why this variable isn't defined yet.

For example, do you really want to test if aVariable has a value set, rather than is or isn't defined?

var aVariable = null;

... (sometime later)

if (aVariable == null) {
  aVariable = value;
}
Fenton
  • 241,084
  • 71
  • 387
  • 401
5

I found more acceptable answers in JSLint mailing list, sorry about that Boldewyn :)

Solution 1

In IE, at a script level (i.e. per file, or per script block), if it sees a "var" declaration during its parse phase (before execution), it will reset the value of that variable if it already existed.

So better would be to simply do this:

/*global foo: true */
if (typeof foo === "undefined") {
foo = "some value";
}

By not declaring "var" and simply assigning foo, foo will automatically get global scope.

Solution 2 (special case)

If explicitly set variable is not zero or false

var foo = foo || "some value";
nimcap
  • 10,062
  • 15
  • 61
  • 69
  • Is there a performance penalty for solution 2? Or any side effects? I suppose I wouldn't be able to change the global foo? – Vanuan May 15 '12 at 13:48
  • Solution 2 seems to have a side effect: page crashed soon after load on Safari (on iOS 6.1.3) when a JS file had the row `var window = window || {};`. Chromium (on Ubuntu 12.04) didn't have such a problem. Strange. – Akseli Palén Sep 12 '13 at 23:48
4

You could make the variable (it's global anyway) an explicit member of window:

window.aVariable = 'default';

and later

if (! ('aVariable' in window)) {
    window.aVariable = 'new value';
}

If you don't want or cannot change the code, then I'd suggest the pragmatic ansatz and to ignore JSLint's complaints, since your code will work anyways (that is, as long as you don't enable ECMAScript 5's strict mode...).

Boldewyn
  • 81,211
  • 44
  • 156
  • 212
2

Try this:

aVariable = null;

aVariable = typeof(aVariable) == 'undefined' ? null : value;
Sarfraz
  • 377,238
  • 77
  • 533
  • 578
1

Easiest to declare your variables before you make any use of them:

var aVariable;

This will be initialized with type "undefined", so the undefined test will still work:

if (typeof aVariable == "undefined") {
    aVariable = value;
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
-1

That error seems to be triggered when you use camel casing for your variable name. If you start the variable with a capital letter (Variable) or make it all lower case (variable), you just get the "implied global" error.

I'm not sure what it's trying to suggest by enforcing casing on your variable name, though you always have to take JSLint with a grain of salt. What you're doing here is perfectly valid and a good practice to avoid accidentally using undefined variables.

Jimmy
  • 35,686
  • 13
  • 80
  • 98
  • Question: *JSLint warns that it is used before it is defined*. How is that related to camel case? And it's *not* perfectly valid, because JSLint is right: The variable *is* used before it is defined. – Boldewyn Feb 10 '10 at 08:00
  • 1
    Read my answer more thoroughly before down voting. It is related to the casing of the variable name the OP used: `aVariable`. Run the same code posted in the question with the variable name written as `avariable`, `AVARIABLE`, or `Avariable` and you'll notice JSLint no longer displays the error. – Jimmy Feb 10 '10 at 08:29
  • So, which JSLint do you use? The one over at http://www.jslint.com/ gives the same result independent from spelling because it has *nothing to do with spelling*. – Boldewyn Feb 10 '10 at 08:45
  • I am not sure how you are getting different results from me. I don't use a "different" JSLint. I just tried it again and had the same result. Copy/paste the OP's code exactly, then change `typeof(aVariable)` to `typeof(avariable)` and you will see the error `'aVariable' was used before it was defined.` no longer shows up. I agree that spelling is insignificant as far as how the variable is treated. I am just pointing out the behavior of JSLint in reporting errors. – Jimmy Feb 10 '10 at 09:10
  • I pasted the first code snippet into JSLint on the home page of jslin.com, got the *JSLint warns that it is used before it is defined* error, changed both instances of `aVariable` to `avariable`, reran JSLint and got exactly the same error. Perhaps you forgot to change the variable name on both lines? – Tim Down Feb 10 '10 at 09:48
  • Even due camel casing is impling globals,they are only impling globals to the user, not the system running the code. – Rafael Herscovici Jan 01 '12 at 15:01