JSLint flags any use of the eval statement with the message eval is evil. This is because eval is a hook right into the JavaScript compiler. It accepts a string as a parameter and then compiles it and runs it.

Further resources on the evils of eval are available through the above link. Here we are more interested in how document.write can equate to eval

So how can document.write possibly equate to being the same? Well, we can demonstrate this with a simple example. You’ll need to set up an HTML page and a JS File with the following code:

HTML File

<script src="a.js" type="text/javascript"></script>

JS File

document.write('<script type="text/javascript">alert(1 + 2);</script>');
alert(eval(1+2));

Or alternatively, download them from my sample: document.write.eval.zip

What happens when you run it? Well, you get “3″ output twice.

The JavaScript compiler picks up the first line, and writes out some more JavaScript, which itself has to be executed and fed back into a compiler. So, in effect, we have a line of JavaScript that is responsible for invoking the compiler again. This first line is sending 1+2 to the compiler to be evaluated.

This is pretty much identical to what is happening with eval(1+2) in our second line.

Of course, the above works because we have separated out our HTML and JS. What if we had it all in a single HTML page. Something like

<script src="a.js" type="text/javascript">
   document.write('<script type="text/javascript">alert(1 + 2);</script>');
</script>

When document.write outputs , it closes the original script tag on the first line. We are then left with a hanging ‘); that is output to the browser and an orphaned closing script tag.

This may not be eval, but it is certainly evil.

So, there we have it document.write can be a form of eval. But it doesn’t have to be eval to be evil. It should, therefore, be avoided.

We can, of course, turn this up simply by turning on the ‘evil’ JSLint option, like so:

/*jslint evil: true */

Thanks to the wisdom of StackOverflow for helping answering this: JSLint “document.write can be a form of eval” – How is this so?

A Guide To JSLint Messages

This article is one of a series on the error and warning messages produced by JSLint.

, , ,

Why Bother?

JSLint contains a number of messages pertaining to the style, appearance and formatting of JavaScript code. This includes stipulations about bracing positions, indentation and spacing.

As a demonstration of this paste the following into http://jslint.com/

var x = 0;
switch(x){
    case 1:
        x++;
        break;
    case 2:
        x--;
        break;
    default:
        break;
}

Zero errors, right? Now click the flag ‘Strict white space’ (‘white’) and recheck…

Yikes! 10 errors (at the time of writing)!

So why should JSLint possibly care what your code looks like? After all, it’s all about bugs, isn’t it?

Well, on the surface, legible code equates to more maintainable code, which itself equates less ambiguity and fewer bugs. But you may have your own internal guidelines that dictate how the JavaScript looks, i.e. how you indent, where you put your braces, etc. So you will have probably flipped the ‘white’ flag to ‘off’. After all, when given the above code snippet, JSLint returns a substantial amount of what you consider to be ‘noise’, which if no use to you. Right?

However in turning this option off, you are missing the opportunity to have a uniform and consistent convention across your code base, and a tool that can tell you where you are deviating from it.

But sometimes, formatting and positioning does have functional implication as well, and can lead itself to bugs. Consider the following code:

function GetObjectLiteral()
{
    return
   {
       x:0,
       y:1
   };
}
alert(GetObjectLiteral().x); //what do you expect?

Regardless of what you expect the above to return, what you will not get is an alert box with the text ’0′. Different browsers may behave differently. IE8 complains about a missing semi-colon, whilst others will simply execute the ‘return’, passing control back to the calling function, and then fail to find the member ‘a’

Changing the bracing position fixes the code:

function GetObjectLiteral(){
    return{
       x:0,
       y:1
   };
}
alert(GetObjectLiteral().x); //alerts '0'

The Messages

So, let’s have a look at some of these messages…

Expected ‘{a}’ at column {b}, not column {c}.

This is a simple case of incorrect indentation. The most basic demonstration of this can be seen in following code snippet:

var a = 0;
  var b = 0; //Problem at line 2 character 3: Expected 'var' at column 1, not column 3

Expected ‘{a}’ to have an indentation of {b} instead of {c}.

This is another indentation catch. The default indentation step is 4, meaning that indentation columns should start at positions 1, 5, 9, 13, 17, etc. The sample below uses an indent of 5 spaces, placing the start of the new column at character 6 (as the message denotes).

function MyFunc() {
     alert("hello"); //Problem at line 2 character 6: Expected 'alert' at column 5, not column 6.
//3456789
}

Expected exactly one space between ‘{a}’ and ‘{b}’.

This message goes some way to supporting JSLint’s assertion of correct bracing positions. You will see this message generated on the following code snippet.

if (x === 0)
{  //brace on next line
    alert("hello");
}

But even when you do place the brace on the correct line, JSLint requires you to apply the correct spacing. So, the following code snippets will also yield this message:

if (x === 0){ //no spaces
    alert("hello");
}

if (x === 0)  {//two spaces
    alert("hello");
}

Missing space between ‘{a}’ and ‘{b}’.

Haveyoutriedreadingsentencesthathavetheirspacesomitted? Generally, it’s not that easy, is it?

if (x === 0){    //Missing space between ')' and '{'
    alert("hello");
}

Mixed spaces and tabs.

This message is displayed when a line is indented with a mixture of spaces and tabs. Most IDEs will have an option to convert tabs into spaces automatically. I suggest you turn this on.

Unexpected space between ‘{a}’ and ‘{b}’

Here, JSLint is reporting that you have included a space where it did not expect one. The following code snippet will yield this message:

if ( x === 0){  //Unexpected space between '(' and 'x'
    alert("hello");
}

A Guide To JSLint Messages

This article is one of a series on the error and warning messages produced by JSLint.

, , ,

JSlint may just occasionally save you from yourself.

The following code is clearly nonsense. The clause will never evaluate to true, and your alert will never be shown:

if (1 === 0) {
    alert("hello");
}

But you’ll also get the JSLint message where the clause does evaluate to true:

if (1 === 1) {
    alert("hello");
}

In general, this message will appear when both sides of the clause are literal values or if they are identical, for example:

if (myVar === myVar) {
    alert("hello");
}

We are not just limited to ‘if’ clauses, either. ‘while’ tests will also yield this error.

A Guide To JSLint Messages

This article is one of a series on the error and warning messages produced by JSLint.

, ,

In a JavaScript ‘switch’ block, JSLint expects every ‘case’ statement to be broken with a ‘default’ keyword.

So, the following code sample will fail:

var x = 0;
switch(x){
    case 1:
        x++;
        //where's the 'break;'?
        //so, 'fall through'
    case 2:
        x--;
        break;
    default:
        break;
}

In this sample, after evaluating ‘true’ for ‘case 1′ and executing the adjacent code, the interpreter will ‘fallthrough‘ to the next clause and test that. In the above code the next clause will evaluate false, so there is not a problem.

Many consider this an advantageous language feature. Consider the scenario where you want to execute the same code under two different circumstances (i.e. implement an ‘or’ equivalent). For example:

var x = 0;
switch(x){
    case 1: //fallthrough
    case 2:
        x--;
        break;
    default:
        break;
}

Douglas Crockford, however considers this to be a little too tricky. In his book ‘JavaScript: the good parts’, he mentions this:

I want to avoid idioms that look like mistakes.

I never allow switch cases to fall through to the next case. I once found a bug in my code caused by an unintended fall though…

He goes on to explain that language features that are sometimes useful, but occasionally dangerous are probably best avoided as it can be difficult for a developer/reviewer/maintainer to differentiate its use from a bug.

A Guide To JSLint Messages

This article is one of a series on the error and warning messages produced by JSLint.

, ,

This one is fairly self-explanatory, so I’m not going to waste too much time on it.

In short, your switch statements really ought to have a ‘case’ statement. Otherwise they are really just pointless, empty blocks. Take the following:

var x = 0;
switch(x){
    default:
        break;
}

It’s hardly surprising that JSLint is going to complain about this.

The ‘why’ here should be obvious. Clearly you have some redundant code that should be removed or have omitted a chunk for functionality.

A Guide To JSLint Messages

This article is one of a series on the error and warning messages produced by JSLint.

, ,

JavaScript isn’t very particular about whether or not you declare your variables (its loosely typed). In fact, you can often get away without doing so. Consider the following:

x = 0;
alert(x);  //alerts '0' quite happily

The about example isn’t overly problematic, but that doesn’t mean that its a sensible thing to do. This, assumes you intended to do this. Consider the following:

var receivedParts = 0;
recievedParts = GetReceivedParts();

Whoops! Can you spot what’s wrong? Yes, we’ve spelled ‘received’ differently (mixed the ‘e’ and ‘i’ in our typing). JavaScript doesn’t care, though.A value is assigned to the latter without complaint.

Of course we might have intended to do this, but even this is inadvisable. Consider the following:

receivedParts = receivedParts + 1;

Our variable isn’t defined, so, again we have a bug.

Of course, in strongly typed languages, this isn’t an issue. In effect, JSLint is attempting to make JavaScript a more strongly typed language.

A Guide To JSLint Messages

This article is one of a series on the error and warning messages produced by JSLint.

, , ,

JavaScript will let you repeat your declarations without complaint, however it’s rarely, if ever, a good idea to do so:

var x = 0;
var x = 1; //no complaints!

JavaScript here will simply disregard the first declaration. The above is clearly nonsense, but there are circumstances in which a developer might declare a variable twice in faith. Consider the following:

if (condition) {
    var x = 0;
} else {
    var x = 1;
}

Here, the developer has made the assumption that JavaScript allows you to scope variables locally. The developer is, of course, wrong in this assumption. All declarations are hoisted to the top of the containing scope. So, in effect we still have two declarations.

The same message is produced for other declarations, e.g. functions:

function foo(){};
function foo(){}; //'foo' is already defined.

Multiple declarations of the same name are subject to confusion and buggy code, and therefore should be avoided.

A Guide To JSLint Messages

This article is one of a series on the error and warning messages produced by JSLint.

, , ,

In JavaScript we can assign a function expression to a variable, like so:

var foo = function() {
    return 1;
}; //assign function expression to 'foo'

This is perfectly valid, and often useful.

It is also possible to assign a variable the return value of the function expression by invoking the function, like so:

var foo = (function() {
    return 1;
}()); //assign '1' to 'foo'

This is also valid, although less commonly useful.

These are two distinct techniques with distinct conventions, so, the following may well give rise to confusion:

var foo = (function() {
    return 1;
});//assign function expression to 'foo'

The above is equivalent to the first sample of code, and will execute in exactly the same way. JSLint encourages you to wrap invoked function expressions with parentheses. Wrapping non-invoked function expressions in the same way may be indicative of something non-intentional, or at very least be misinterpreted by a future developer.

In other words, stick to the first convention for the assignment of function expressions.

A Guide To JSLint Messages

This article is one of a series on the error and warning messages produced by JSLint.

, , , ,