In this chapter on JavaScript Essentials we touch on several basic topics that every JavaScript developer should be aware of: case-sensitivity, linting, and the pitfalls and risks of the eval() function.:
JavaScript is case-sensitive. Keywords such as for
and
function
, must be in their proper case (i.e. lowercase)
and not For
and Function
,
or FOR
and FUNCTION
.
Similarly, totalamount
,
totalAmount
, TotalAmount
, and
totalAMOUNT
are 4 distinct variable names in JavaScript.
When using JavaScript in a browser it is important to realize that HTML
is not case-sensitive which may lead to some confusion. For instance,
event attribute names can be typed in any case in HTML, so both
onclick
and onClick
work.
In JavaScript, it is typically all lowercase.
<!-- the same --> <a href="index.html" onclick="handler();" /> <a href="index.html" onClick="handler();" />
Coding conventions and naming standards are important for JavaScript programmers.
Most use camelCase for their variable and function names,
such as, savingsAccount
and computeProfits
.
Constructor functions are by convention written in PascalCase,
such as, Employee
and LegalDocument
.
Iterator variables are commonly single character lower case letters, such
as i
, j
, and k
,
as in for (var i = 0; i < 10; i++) {…}
.
Each JavaScript project should use a consistent set of coding standards and naming conventions. This is particularly important when the project is a team effort. Ideally, when exploring a project's code base, it should feel as if it's written by a single developer. This consistency ensures that all parts of the program are easy to support, irrespective who on the team wrote it.
To get your project off to a good start we have included a list of modern naming conventions and coding standards for JavaScript in our Dofactory JS. To learn more click here.
Linting is the process of scanning and analyzing source code to detect programming errors, bugs, stylistic mistakes, and suspicious constructs. In JavaScript, JSLint is a commonly used linter to analyze code for quality.
JavaScript is a weakly typed language which limits the compiler to check for errors before runtime. Because of this, the risk of bugs slipping through is fairly high. This is where JSLint comes to the rescue. It enforces some level of discipline that is otherwise lacking in JavaScript programming.
As an example, most browsers will let you get away with code like this:
function x() { arr = new Array() arr['num1'] = "012" no = parseInt( arr['num1'] ) if(nov == 12) for (i=0;i<arr.length;i++) if(arr[i] != null) return true return false };
However, when you pass this code through JSLint it will report more than a dozen problems! See how many you can find without viewing the JSLint report.
JSLint catches several categories of bugs before they get to the browser. For instance, having a comma after the last element in an array is invalid in JavaScript, but most browsers ignore it and don't complain. However, IE reports an error message "Unexpected identifier, string or number". JSLint helps to detect this kind of syntax errors.
JSLint requires the code to be compliant with strict mode; all variables and functions
need to be declared before they are used or invoked. It favors the use of strict equality
operators, that is ===
and !==
,
over these ==
and !=
which do not
perform type conversion. JSLint discourages the use of eval()
,
with
, ++
, --
,
void
, and bitwise operators. It also expects constructor
function names to start with an uppercase letter.
To prevent unintended fall-through in a switch statement, JSLint requires that the statement before the next case is either, a break, a return, or a throw statement. It expects new objects to be created with {} rather than new Object. It ensures that all JSON data structures are well formed. It also looks for unreachable code, improperly escaped characters in regular expressions, and UTF characters that are considered unsafe.
JSLint recommends using a global declaration comment to let it identify the names of all your global variables. This helps JSLint find variable declarations you misspelled or forgot to prefix with a var. A declaration comment must appear before the variables specified are used, for example:
/* global totalCount, totalSales */ ... var totalCount = 0; var totalSales = 0;
JSLint is highly configurable and its options are specified on top of the script as a sequence of name-value pairs in your code, where the name is a JSLint option and its value is either true or false. The default of all values is false. Here is an example:
/* jslint cap:true, debug:true, passfail:true, evil:false, plusplus:false */
The first three options: cap, debug, and passfail are all set to true, indicating
that uppercase HTML is allowed, debugger statements are allowed, and that the scan
should stop on the first error it detects. The evil (not a typo!) and plusplus options
are set to false indicating that the use of eval()
and
++
and --
operators is not allowed.
JSLint even examines the HTML trying to locate problems that are known to frequently occur with JavaScript. It expects all HTML tag names to be lowercase and be nested correctly. Also, it ensures that you use < for a < literal.
A fork of JSLint, called JSHint, is rather popular. Among other things, it is far more configurable than JSLint so that it can handle different coding styles. Whichever you use, be sure that you 'lint' or 'hint' your JavaScript programs.
In this section we will review JavaScript's eval()
function
and its potential security pitfalls.
The built-in eval()
function accepts a string as an argument.
If the argument is a valid JavaScript expression, eval()
evaluates
the expression and returns its value. For example, eval("6+4")
returns 10.
If the argument is one or more JavaScript statements, or an entire program,
eval()
will happily execute them all and returns the
value of the last statement.
While eval()
is a powerful way to dynamically execute
JavaScript code, it is also dangerous and has security implications associated
with it. A hacker could easily inject rogue code that might compromise the security
of your application. This is known as code injection.
In reality, when the code is known in advance, there really is no need to dynamically execute it. This is only needed if you dynamically generate code at runtime. For instance, suppose you have an object, called car, and want to access a property on it and you don't know the property's name until runtime.
var car = {};
var property = "color";
eval("car." + property + " = 'white';");
console.log(car[property]); // => white
Although it works, there are several problems with this code. First, it is harder to read and maintain. Second, execution of this type of code is considerably slower because JavaScript will have to go back into the compiler/interpreted mode in the midst of runtime just to execute this trivial statement. Third, it hinders the ability of JSLint to identify problems to a great extent. Finally, and most importantly, a hacker may be able to inject code with consequences that you never anticipated.
Instead of using literal dot-names to access the dynamic properties, make use of the square bracket notation which is much better and simpler way to achieve the same result.
var car = {};
var property = "color";
car[property] = 'white';
console.log(car[property]); // => white
With all these pitfalls and security risks it is best to avoid the use
of eval()
altogether.