Primitive types: number, string, Boolean, null, undefined

JavaScript supports only a handful of data types. The primitive types are number, string, Boolean, and two special types: null and undefined. These are referred to as primitive types because they are the basic, ready-to-use variable types that are built into the language.

The number variable type

JavaScript's number is the only type to hold numbers. It does not distinguish between byte, integer, long, double, or any other numeric type. As far as JavaScript is concerned a number is a number. Most programming languages support a separate integer type, but JavaScript does not. The implication of this is that in JavaScript the values 10, 10.0, and 1e1 are all the same.

var a = 10;     
var b = 10.0;
var c = 1e1;
alert(a === b);     // => true
alert(a === c);     // => true
alert(b === c);     // => true
Run

Here are some valid numeric literals: 1, 209, -8, 4.5, -99.9999, 3e2.

JavaScript supports two special numeric values: NaN and Infinity. They are discussed on the page about 'JavaScript Operators'.

The string variable type

JavaScript's strings are immutable sequences of characters. String literals are enclosed by single or double quotes, like so: "Hello" or 'Hello'. Once created a string cannot be changed (this is what immutable refers to). However, it is easy to create a new string by manipulating existing strings, such as: "Hello".substr(3), which creates a new string with "lo" as its value. JavaScript does not support the single character (char) type, but you can easily use a single character string, such, as "a", or "Y".

Here are some string examples:

var s = "Hello World";
var t = s.substr(6);      // new string 
alert(t);                 // => World
Run

The Boolean variable type

Like in other languages, JavaScript's Boolean has two possible values: true and false. Note that true and false are language keywords and they are distinct from 1 and 0.

var b = false;
alert(b);                // => false (i.e. not 0)
Run

null and undefined

Both null and undefined can be regarded as a special value that indicates "no value".

The null is a language keyword (in fact, it is an object) which is used to indicate the expected lack of value. On the other hand, undefined is a predefined global variable that has a deeper meaning and is used to indicate an error-like, unexpected lack of value.

When your function has no return value, it returns undefined. If you declare a variable and don't initialize it, it returns the undefined value. If you query a non-existent array element or object property, again an undefined is returned. Here is an example.

var book;        
     
alert(book);          // => undefined
alert(typeof book);   // => undefined 
Run

If you want to indicate the 'lack of value' in your code, you typically use null rather than undefined.

var book = null;  
      
alert(book);          // => null
alert(typeof book);   // => object  (although null is not a true object)
Run

Both null and undefined qualify as false when a Boolean value is required. They don't have any properties. If you attempt to access a property on them, an exception will be raised.

It is considered good practice to leave the use of undefined to JavaScript. In other words, let JavaScript determine if something is undefined, rather than you setting variables or properties to undefined. If your app requires that a variable or property value is unknown, give it a value of null and not undefined.

It is interesting to note that undefined is implemented as a global variable named 'undefined'. Its value is undefined. Since it is a global variable, there is nothing that prevents a malicious coder from re-assigning the value of undefined to something else, like so:

// hacker's code
undefined = true;

Clearly, this will wreak havoc with many JavaScript programs. Our JavaScript + jQuery Design Pattern Framework has a lot more to say about this attack and ways to protect your code against this risk. To learn more click here.





Declaring JavaScript variables

Variables in JavaScript are declared with the var keyword. You have several options on structuring your variable declaration and initialization:

// declaring one variable
var cost;                    
// declaring multiple variables, delimited by commas
var cost, profit;            
// declaring and assigning one variable
var cost = 120;              
// declaring and assigning multiple variables
var cost = 120, profit = 77; 

You can declare one variable at a time.

Let's look at variable naming rules. A variable name can contain any combination of alpha-numeric characters, the $ sign, and the underscore character. Its first character cannot be a digit. Variable names cannot contain space characters or any of the punctuation characters. Here are some examples of valid variable identifiers:

var _groupName_;
var $bicycle12; 
var ABH;
var particle_X_Y;
var abc$123;
var easy;

Implied global variables

If a variable is not declared explicitly (using var), then JavaScript will automatically treat it as a global variable. This can hide misspelled and forgotten variable declarations and consequently introduce bugs in your program. This is demonstrated below. The variable count is missing a var and will be created implicitly. The variable reslt is a misspelling of 'result' and a new global variable named 'reslt' will be created. Worse, the original result value will always remain false.

count = 4;                 // => global count is created
var result = false;
if (condition === true) {
    reslt = true;          // => global reslt is created!
}

As you can see, typos are not called out in JavaScript and can lead to subtle and hard-to-detect bugs.

JSLint uncovers implied global variables and requires that you declare them explicitly using the var keyword before they are assigned a value. Using var also improves program readability. Even if you use var, you still have to be careful when chaining declarations and assignments. In the following code all seems fine, but total is a local variable, but summary is an implied global.

function calculate() {
   var total = summary = 0;   // => summary is implied global variable
   ...
}

The expression summary = 0 is evaluated first. Since summary is not declared, it is treated as global. The expression returns the value 0 which is further assigned to the variable total. Because total is declared with a var keyword, it is a local variable with function scope.

Variables as properties

When declaring a global variable, you are actually defining a property on the global object. If the global variable is created with var, the property that is created cannot be deleted (undefined) with the delete operator. On the other hand, implied globals can be deleted.

var a = 1;        // => explicit global
b = 2;            // => implied global
delete a;         // => cannot delete
delete b;         // => deleted




Variable scoping

The scope of the variable determines its visibility and its lifetime. Visibility determines the portions of the program in which it can be 'seen' and referenced. Lifetime is the period during execution of a program in which a variable or function exists

In programming, variable scoping is an important concept. JavaScript supports two scope-levels, global and functional, which are discussed next.

Global scope and function scope

In JavaScript, all variables that are defined outside functions are globally scoped; this means they are visible and accessible anywhere in the program. Variables that are defined inside a function have function scope, meaning they are only visible and accessible within the function, for the duration of that function.

In the example below variable g is global and is visible anywhere, including the function. The variables u and c are only visible within the function. It is said that variable g has global scope and variables u and c have function scope.

var g = "World";           // global scope
function countries() {
    var u = "US";          // function scope
    var c = "China";       // function scope
    alert(g);              // => World
    alert(u);              // => US
    alert(c);              // => China
}
countries();
alert(g);                  // => World
alert(typeof u);           // => undefined
Run

The last line demonstrates the variable u is not visible outside the countries() function.

Function scope hides global scope

If you declare a local variable inside a function with the exact same name as a global variable, then the local variable will hide the global variable. In the next example, the local client variable hides the global client variable.

var client = "Joan";            // global
function getClient() {
   var client = "Timothy";      // local, hides global
   return client;
}
alert(getClient());             // => "Timothy"
Run

JavaScript does not support block scope

In C-like languages, when control enters a code block (for example an if statement enclosed by brackets), then local variables defined within the block will have their own execution context and are destroyed when the closing block brace is encountered. However, JavaScript does not support block-level scoping, only function and global level scoping.

In the example below, the client variable in the if-block refers to the global variable. There is no hiding or anything of that nature, just one global variable named client.

var client = "Joan";
if (true) {
   var client = "Timothy";   // refers to global variable
   alert(client);            // => "Timothy" 
}
alert(client);               // => "Timothy"
Run

Looping variables

When using variables in for loops you have to be careful because they continue to exist outside the loop. In the example below, the for-statement creates the variable i which continues to exist outside the loop, even after the for-statement finishes execution. Most other languages that support block level scoping the looping variables cease to exist outside the for loop.

for (var i = 0; i < 5; i++) {
    // do something 
}
alert(i);     // => 5
Run



Variable and function hoisting

The JavaScript compiler invisibly moves (hoists) all the variables to the top of their containing scope. Consider this code:

function f() {
    doSomething();
    var count;
}

JavaScript transforms this code to this:

function f() {
    var count;               // hoisted
    doSomething();
}

All variables that you declare inside a function are visible throughout the function body (this is what we mean with function scope). This implies that variables are visible even before they are declared, but using a variable before it is initialized can lead to bugs. Here is an example:

var x = 1;
function f () {
    alert(x);        // => undefined
    var x = 2;
}

Notice we have a global variable x and a local variable x. The undefined result may surprise you. Perhaps you expected a value of 1 or possibly 2, but not undefined. It's all because of hoisting which involves the variable declaration, but does not include the assignment portion. Here is how the code executes:

var x = 1;
function f () {
    var x;        // hoisted. hides global variable, but is unitialized.
    alert(x);     // => undefined 
    x = 2;
}

Function hoisting

Not only variables, but also functions are hoisted. Consider the following code:

var text = "Hello";
function f() {
   text = "Greetings";
   return;
   function text() {}
}
f();
alert(text);            // => "Hello"
Run

What is going on here? Well, the compiler lifts (hoists) the local function text() to the top of f()'s function body. Since declarations are function-scoped, the assignment of "Greetings" is made to the local text instance (which is a function) and, therefore, the global text variable remains unchanged. The code executes like this:

var text = "Hello";
function f() {
   function text() {}    // local variable text. Hides global text.
   text = "Greetings";   // local assignment to function named text
   return;
}
f();
alert(text);            // => "Hello"
Run

Finally, consider this example in which two local print functions are within an if-else statement:

function f() {
  var condition = true;
  if (condition) {
     function print() { alert("true"); };
  } else {
     function print() { alert("false"); };
  }
  print();               // => true or false (depending on browser)
}
f();
Run

We know that functions get hoisted, so what will happen? Since the value of condition is true, you may expect that the print() inside the if block will execute. But this is not the case. IE prints false and Firefox prints true. What this indicates is that hoisting is not concerned about the runtime code, that is, at compile time the conditions in the if-else statements are irrelevant. Also, there are no definite rules that dictate which function declaration shall prevail over the others.

The lesson learned here is that side effects of implicit global variables and of hoisting can result in hard-to-find bugs. Our JavaScript + jQuery Design Pattern Framework offers proven patterns and best practice techniques to minimize these kinds of problems. To learn more click here.