![]() ![]() |
![]() ![]() ![]() ![]() ![]() ![]() |
|
||||||||
There are some additional characters which are rarely used: \b (backspace), \v (vertical tab), and \f (form feed). BooleansThere are only two values that belong to the boolean data type: the values true and false, used without quotes. >>> var b = true; typeof b;
"boolean"
>>> var b = false; typeof b;
"boolean"
If you quote true or false, they become strings. >>> var b = "true"; typeof b;
"string"
Logical OperatorsThere are three operators, called logical operators, that work with boolean values. These are:
In everyday meaning, if something is not true, it is false. Here's the same statement expressed using JavaScript and the logical ! operator. >>> var b = !true;
>>> b;
false
If you use the logical NOT twice, you get the original value: >>> var b = !!true;
>>> b;
true
If you use a logical operator on a non-boolean value, the value is converted to boolean behind the scenes. >>> var b = "one";
>>> !b;
false
In the case above, the string value "one" was converted to a boolean true and then negated. The result of negating true is false. In the next example, we negate twice so the result is true. >>> var b = "one";
>>> !!b;
true
Using double negation is an easy way to convert any value to its boolean equivalent. This is rarely useful, but on the other hand understanding how any value converts to a boolean is important. Most values convert to true with the exception of the following (which convert to false):
These six values are sometimes referred to as being falsy, while all others are truthy (including, for example, the strings "0", " ", and "false"). Let's see some examples of the other two operators—the logical AND and the logical OR. When you use AND, the result is true only if all of the operands are true. When using OR, the result is true if at least one of the operands is true. >>> var b1 = true; var b2 = false;
>>> b1 || b2
true
>>> b1 && b2
false
Here's a table that lists the possible operations and their results:
You can use several logical operations one after the other: >>> true && true && false && true
false
>>> false || true || false
true
You can also mix && and || in the same expression. In this case, you should use parentheses to clarify how you intend the operation to work. Consider these: >>> false && false || true && true
true
>>> false && (false || true) && true
false
Operator PrecedenceYou might wonder why the expression above ( false && false || true && true) returned true. The answer lies in operator precedence. As you know from mathematics: >>> 1 + 2 * 3
7
This is because multiplication has precedence over addition, so 2 * 3 is evaluated first, as if you've typed: >>> 1 + (2 * 3)
7
Similarly for logical operations, ! has the highest precedence and is executed first, assuming there are no parentheses that demand otherwise. Then, in the order of precedence, comes && and finally ||. In other words: >>> false && false || true && true
true
is the same as: >>> (false && false) || (true && true)
true
Lazy EvaluationIf you have several logical operations one after the other, but the result becomes clear at some point before the end, the final operations will not be performed, because they can't affect the end result. Consider this: >>> true || false || true || false || true
true
Since these are all OR operations and have the same precedence, the result will be true if at least one of the operands is true. After the first operand is evaluated, it becomes clear that the result will be true, no matter what values follow. So the JavaScript engine decides to be lazy (ok, efficient) and not do unnecessary work by evaluating code that doesn't affect the end result. You can verify this behavior by experimenting in the console: >>> var b = 5;
>>> true || (b = 6)
true
>>> b
5
>>> true && (b = 6)
6
>>> b
6
This example also shows another interesting behavior—if JavaScript encounters a non-boolean expression as an operand in a logical operation, the non-boolean is returned as a result. >>> true || "something"
true
>>> true && "something"
"something"
This behavior is something to watch out for and avoid, because it makes the code harder to understand. Sometimes you might see this behavior being used to define variables when you're not sure whether they were previously defined. In the next example, if the variable v is defined, its value is kept; otherwise, it's initialized with the value 10. var mynumber = mynumber || 10; This is simple and looks elegant, but be aware that it is not completely bulletproof. If mynumber is defined and initialized to 0 (or to any of the six falsy values), this code might not behave in exactly the way it was designed to work. ComparisonThere's another set of operators that all return a boolean value as a result of the operation. These are the comparison operators. The following table lists them, together with some examples.
An interesting thing to note is that NaN is not equal to anything, not even itself. >>> NaN == NaN
false
Undefined and nullYou get the undefined value when you try to use a variable that doesn't exist, or one that hasn't yet been assigned a value. When you declare a variable without initializing it, JavaScript automatically initializes it to the value undefined. If you try using a non-existing variable, you'll get an error message. >>> foo
foo is not defined
If you use the typeof operator on a non-existing variable, you get the string "undefined". >>> typeof foo
"undefined"
If you declare a variable without giving it a value, you won't get an error when you use that variable. But the typeof still returns "undefined". >>> var somevar;
>>> somevar
>>> typeof somevar
"undefined"
The null value, on the other hand, is not assigned by JavaScript behind the scenes; it can only be assigned by your code. >>> var somevar = null
null
>>> somevar
null
>>> typeof somevar
"object"
Although the difference between null and undefined is small, it may be important at times. For example, if you attempt an arithmetic operation, you can get different results: >>> var i = 1 + undefined; i;
NaN
>>> var i = 1 + null; i;
1
This is because of the different ways null and undefined are converted to the other primitive types. Below are examples that show the possible conversions. Conversion to a number: >>> 1*undefined
NaN
>>> 1*null
0
Conversion to a boolean: >>> !!undefined
false
>>> !!null
false
Conversion to a string: >>> "" + null
"null"
>>> "" + undefined
"undefined"
Primitive Data Types RecapLet's quickly summarize what has been discussed so far:
ArraysNow that you know the basic primitive data types in JavaScript, it's time to move to a more interesting data structure—the array. To declare a variable that contains an empty array, you use square brackets with nothing between them: >>> var a = [];
>>> typeof a;
"object"
typeof returns "object", but don't worry about this for the time being, we'll get to that when we take a closer look at objects. To define an array that has three elements, you do this: >>> var a = [1,2,3]; When you simply type the name of the array in the Firebug console, it prints the contents of the array: >>> a
[1, 2, 3]
So what is an array exactly? It's simply a list of values. Instead of using one variable to store one value, you can use one array variable to store any number of values as elements of the array. Now the question is how to access each of these stored values? The elements contained in an array are indexed with consecutive numbers starting from zero. The first element has index (or position) 0, the second has index 1 and so on. Here's the three-element array from the previous example:
In order to access an array element, you specify the index of that element inside square brackets. So a[0] gives you the first element of the array a, a[1] gives you the second, and so on. >>> a[0]
1
>>> a[1]
2
Adding/Updating Array ElementsUsing the index, you can also update elements of the array. The next example updates the third element (index 2) and prints the contents of the new array. >>> a[2] = 'three';
"three"
>>> a
[1, 2, "three"]
You can add more elements, by addressing an index that didn't exist before. >>> var a = [1,2,3];
>>> a[6] = 'new';
"new"
>>> a
[1, 2, 3, undefined, undefined, undefined, "new"]
If you add a new element, but leave a gap in the array, those elements in between are all assigned the undefined value. Check out this example: >>> var a = [1,2,3];
>>> a[6] = 'new';
"new"
>>> a
[1, 2, 3, undefined, undefined, undefined, "new"]
Deleting ElementsIn order to delete an element, you can use the delete operator. It doesn't actually remove the element, but sets its value to undefined. After the deletion, the length of the array does not change. >>> var a = [1, 2, 3];
>>> delete a[1];
true
>>> a
[1, undefined, 3]
Arrays of arraysAn array can contain any type of values, including other arrays. >>> var a = [1, "two", false, null, undefined];
>>> a
[1, "two", false, null, undefined]
>>> a[5] = [1,2,3]
[1, 2, 3]
>>> a
[1, "two", false, null, undefined, [1, 2, 3]]
Let's see an example where you have an array of two elements, each of them being an array. >>> var a = [[1,2,3],[4,5,6]];
>>> a
[[1, 2, 3], [4, 5, 6]]
The first element of the array is a[0] and it is an array itself. >>> a[0]
[1, 2, 3]
To access an element in the nested array, you refer to the element index in another set of square brackets. >>> a[0][0]
1
>>> a[1][2]
6
Note also that you can use the array notation to access individual characters
inside >>> var s = 'one';
>>> s[0]
"o"
>>> s[1]
"n"
>>> s[2]
"e"
There are more ways to have fun with arrays (and we'll get to that in Chapter 4), but let's stop here for now, remembering that:
Conditions and LoopsConditions provide a simple but powerful way to control the flow of execution through a piece of code. Loops allow you to perform repeating operations with less code. Let's take a look at:
Code BlocksLet's start by clarifying what a block of code is, as blocks are used extensively when constructing conditions and loops. A block of code consists of zero or more expressions enclosed in curly brackets. {
var a = 1;
var b = 3;
}
You can nest blocks within each other indefinitely: {
var a = 1;
var b = 3;
var c, d;
{
c = a + b;
{
d = a - b;
}
}
}
Ready to jump into loops and ifs? Note that the examples in the following sections require you to switch to the multi-line Firebug console. if ConditionsHere's a simple example of an if condition: var result = '';
if (a > 2) {
result = 'a is greater than 2';
}
The parts of the if condition are:
The condition (the part in parentheses) always returns a boolean value and
There can also be an optional else part of the if condition. The else statement is followed by a block of code to be executed if the condition was evaluated to false. if (a > 2) {
result = 'a is greater than 2';
} else {
result = 'a is NOT greater than 2';
}
In between the if and the else, there can also be an unlimited number of else if conditions. Here's an example: if (a > 2 || a < -2) {
result = 'a is not between -2 and 2';
} else if (a === 0 && b === 0) {
result = 'both a and b are zeros';
} else if (a === b) {
result = 'a and b are equal';
} else {
result = 'I give up';
}
You can also nest conditions by putting new conditions within any of the blocks. if (a === 1) {
if (b === 2) {
result = 'a is 1 and b is 2';
} else {
result = 'a is 1 but b is not 2';
}
} else {
result = 'a is not 1, no idea about b';
}
Checking if a Variable ExistsIt's often useful to check whether a variable exists. The laziest way to do this is simply putting the variable in the condition part of the if , for example if (somevar) {...} , but this is not necessarily the best method. Let's take a look at an example that tests whether a variable called somevar exists, and if so, sets the result variable to yes : >>> var result = '';
>>> if (somevar){result = 'yes';}
somevar is not defined
>>> result;
""
This code obviously works, because at the end result was not "yes". But firstly, the code generated a warning: somevar is not defined and as a JavaScript whiz you don't want your code to do anything like that. Secondly, just because if (somevar) returned false doesn't mean that somevar is not defined. It could be that somevar is defined and initialized but contains a falsy value, like false or 0. A better way to check if a variable is defined is to use typeof. >>> if (typeof somevar !== "undefined"){result = 'yes';}
>>> result;
""
typeof will always return a string and you can compare this string with "undefined". Note that the variable somevar may have been declared but not assigned a value yet and you'll still get the same result. So when testing with typeof like this, you're really testing whether the variable has any value (other than the value undefined). >>> var somevar;
>>> if (typeof somevar !== "undefined"){result = 'yes';}
>>> result;
""
>>> somevar = undefined;
>>> if (typeof somevar !== "undefined"){result = 'yes';}
>>> result;
""
If a variable is defined and initialized with any value other than undefined, its type returned by typeof is no longer "undefined". >>> somevar = 123;
>>> if (typeof somevar !== "undefined"){result = 'yes';}
>>> result;
"yes"
Alternative if SyntaxWhen you have a very simple condition you can consider using an alternative if syntax. Take a look at this: var a = 1;
var result = '';
if (a === 1) {
result = "a is one";
} else {
result = "a is not one";
}
The if condition can be expressed simply as: var result = (a === 1) ? "a is one" : "a is not one"; You should only use this syntax for very simple conditions. Be careful not to abuse it, as it can easily make your code unreadable. The ? is called ternary operator. SwitchIf you find yourself using an if condition and having too many else if parts, you could consider changing the if to a switch. var a = '1';
var result = '';
switch (a) {
case 1:
result = 'Number 1';
break;
case '1':
result = 'String 1';
break;
default:
result = 'I don\'t know';
break;
}
result;
The result of executing this will be "String 1". Let's see what the parts of a switch are:
In other words, the step-by-step procedure for executing a switch statement is as follows:
Loopsif-else and switch statements allow your code to take different paths, as if you're at a crossroads and decide which way to go depending on a condition. Loops, on the other hand, allow your code to take a few roundabouts before merging back into the main road. How many repetitions? That depends on the result of evaluating a condition before (or after) each iteration. Let's say you are (your program execution is) traveling from A to B. At some point, you reach a place where you evaluate a condition C. The result of evaluating C tells you if you should go into a loop L. You make one iteration. Then you evaluate the condition once again to see if another iteration is needed. Eventually, you move on your way to B. An infiniteloop is when the condition is always true and your code gets stuck in the loop "forever". This is, of course, is a logical error and you should look out for such scenarios. In JavaScript, there are four types of loops:
While Loopswhile loops are the simplest type of loop. They look like this: var i = 0;
while (i < 10) {
i++;
}
The while statement is followed by a condition in parentheses and a code block in curly brackets. As long as the condition evaluates to true, the code block is executed over and over again. Do-while loopsdo-while loops are a slight variation of the while loops. An example: var i = 0;
do {
i++;
} while (i < 10)
Here, the do statement is followed by a code block and a condition after the block. This means that the code block will always be executed, at least once, before the condition is evaluated. If you initialize i to 11 instead of 0 in the last two examples, the code block in the first example (the while loop) will not be executed and i will still be 11 at the end, while in the second ( do-while loop), the code block will be executed once and i will become 12. For Loopsf or is the most widely used type of loop and you should make sure you're comfortable with this one. It requires a just little bit more in terms of syntax. In addition to the condition C and the code block L, you have the following:
The most widely used pattern of using a for loop is:
Here's an example: var punishment = '';
for (var i = 0; i < 100; i++) {
punishment += 'I will never do this again, ';
}
All three parts (initialization, condition, increment) can contain multiple expressions separated by commas. You can rewrite the example and define the variable punishment inside the initialization part of the loop. for (var i = 0, punishment = ''; i < 100; i++) {
punishment += 'I will never do this again, ';
}
Can you move the body of the loop inside the increment part? Yes, you can, especially as it's a one-liner. This will give you a loop that looks a little awkward, as it has no body: for (var i = 0, punishment = '';
i < 100;
i++, punishment += 'I will never do this again, ')
{
// nothing here
}
These three parts are actually all optional. Here's another way of rewriting the same example: var i = 0, punishment = '';
for (;;) {
punishment += 'I will never do this again, ';
if (++i == 100) {
break;
}
}
Although the last rewrite works exactly the same way as the original, it is longer and harder to read. It's also possible to achieve the same result by using a while loop. But for loops make the code tighter and more robust, because the mere syntax of the for loop makes you think about the three parts (initialization, condition, increment) and thus, helps you reconfirm your logic and avoid situations such as being stuck in an infinite loop. for loops can be nested within each other. Here's an example of a loop that is nested inside another loop and assembles a string containing 10 rows and 10 columns of asterisks. Think of i being the row and j being the column of an "image". var res = '\n';
for(var i = 0; i < 10; i++) {
for(var j = 0; j < 10; j++) {
res += '* ';
}
res+= '\n';
}
The result is a string like: " * * * * * * * * * * " Here's another example that uses nested loops and a modulus operation in order to draw a little snowflake-like result. var res = '\n', i, j;
for(i = 1; i <= 7; i++) {
for(j = 1; j <= 15; j++) {
res += (i * j) % 8 ? ' ' : '*';
}
res+= '\n';
}
" * " For-in LoopsThe for-in loop is used to iterate over the elements of an array (or an object, as we'll see later). This is its only use; it cannot be used as a general-purpose repetition mechanism that replaces for or while. Let's see an example of using a for-in to loop through the elements of an array. But bear in mind that this is for informational purposes only, as for-in is mostly suitable for objects, and the regular for loop should be used for arrays. In this example, we'll iterate over all of the elements of an array and print out the index (the key) and the value of each element: var a = ['a', 'b', 'c', 'x', 'y', 'z'];
var result = '\n';
for (var i in a) {
result += 'index: ' + i + ', value: ' + a[i] + '\n';
}
The result is: " CommentsOne last thing for this chapter: comments. Inside your JavaScript code you can put comments. These are ignored by the JavaScript engine and don't have any effect on how the program works. But they can be invaluable when you revisit your code after a few months, or transfer the code to someone else for maintenance. Two types of comments are allowed:
Some examples: // beginning of line
var a = 1; // anywhere on the line
/* multi-line comment on a single line */
/*
comment
that spans
several lines
*/
There are even utilities, such as JSDoc, that can parse your code and extract meaningful documentation based on your comments. SummaryIn this chapter, you learned a lot about the basic building blocks of a JavaScript program. Now you know the primitive data types:
You also know quite a few operators:
Then you learned how to use arrays to store and access data, and finally you saw different ways to control the flow of your program—using conditions ( if-else or switch) and loops ( while, do-while, for, for-in). This is quite a bit of information and it is recommended that you now go through the exercises below, then give yourself a well-deserved pat on the back before diving into the next chapter. More fun is coming up! Exercises
|