Assigning Variables with the var Statement
Problem
When programming (just like in algebra), you need to be able to assign a variable piece of data to a keyword that you can reference in your code, for example x = 5.
Solution
With JavaScript, variable assignment needs to be declared using a keyword, which helps to determine the behavior of a variable. The most common way to do this is with the var statement. When defining a variable, one must use the var statement to tell JavaScript you are about to declare one or more variables.
The Code
var a; // The variable "a" has been declared
var a, b; // Both the variable "a" and the variable "b" have been declared.
var a, b, c, d; // The 4 variables; "a", "b", "c" and "d" have all been declared.
var a = 1, b; // The variables "a" and "b" have been declared, and variable "a" has been assigned the number 1 and "b" is undefined.
var a = 1, b = 2; // The variables "a" and "b" have been declared, variable "a" is assigned to the number 1, and "b" is assigned to the number 2
Listing 1-1.
Assigning Variables with the var Statement
How It Works
The JavaScript interpreter will see the var keyword, followed by a set of variable names, with optionally assigned values. It knows this is a VariableDeclaration statement, and it will declare those variables, then assign them. You can now continue to use the variable names and do not have to use their values. This is very similar to how algebra works; for example, you may say a = 5, b = a/2. You’re assigning a to 5 and assigning b to half of a, which is half of 5, so b becomes 2.5. You would do this almost identically in JavaScript, but simply add the var keyword and end with a semicolon
: var a = 5, b = a/2;
Solving Errors with Variable Names
Problem
You attempted to declare a variable, but during runtime your code throws an Error, not letting you assign that variable name. You are presented with one of the following errors
:
SyntaxError: Unexpected token <name>
SyntaxError: Unexpected number
SyntaxError: Unexpected string
SyntaxError: Unexpected reserved word
SyntaxError: missing variable name
SyntaxError: <name> is a reserved identifier
SyntaxError: Use of reserved word '<name>'
SyntaxError: Expected an identifier but found '<name>' instead
SyntaxError: The use of a keyword for an identifier is invalid
SyntaxError: Expected identifier
SyntaxError: Expected string '<name>'
SyntaxError: Expected number '<name>'
SyntaxError: Expected an identifier but found '<name>' instead
Solution
Variable names have a strict set of rules. You must not pick a variable name that is a keyword (these are words already used in the language) or a reserved word (these are words which are reserved for future use), or literal values (the value of a literal, such as true or null). The full list of reserved words
is shown in Table 1-1.
Table 1-1.
Reserved Keywords in JavaScript
break | case | catch | class | const | continue |
---|---|---|---|---|---|
debugger
|
default
|
delete
|
do
|
else
|
enum
|
export
|
extends
|
false
|
finally
|
for
|
function
|
if
|
implements
|
import
|
in
|
Infinity
|
instanceof
|
interface
|
let
|
NaN
|
new
|
null
|
package
|
private
|
protected
|
public
|
return
|
static
|
super
|
switch
|
this
|
throw
|
true
|
try
|
typeof
|
undefined
|
var
|
void
|
while
|
with
|
yield
|
In addition to having a set of reserved words, JavaScript has some other rules around variable naming. They can include numbers, but cannot start with a number (this would confuse them with number literals, discussed later in this chapter in longer detail in Chapter 4), they also cannot contain any spaces. Generally speaking though, the names of JavaScript variables are quite flexible—perhaps too flexible, for example you could use “
” as a variable name (but please don’t). As a good rule of thumb, it is recommended you name your variables using the English Alphabet (A-Z), avoid the use of numbers, and use camelCasing for multiple word variables.
camelCasing
is where each word is given a capital letter, except for the first word. The rest of the letters are lowercase. For example if you had a variable called Number of Days, in camelCase that would be numberOfDays. As another example, a variable called Cache Control would be cacheControl. Examples of camelCasing in the real world are brands like iPhone or eBay.
While you should use camelCasing
for variable names, there are a few exceptions to this best practice rule. One is with
constructors
(functions that create new objects with the new keyword), which should use TitleCase (camelCase but with a capital
first letter). Another is constants, which should be UPPERCASE_WITH_UNDERSCORES. Of course, all of these are best practices, and so can be disobeyed, but it is strongly recommended to use them.
It is very important to note that JavaScript variable names are case sensitive, that is byteLength is a different variable than ByteLength, which is a different variable than BYTE_LENGTH and so on. This is why it is vitally important to stick to a good naming convention for your variables. It can be very easy to get caught by inconsistent naming schemes, and spend hours debugging code only to find your variable was missing an uppercase character.
The Code
Listing 1-2. Rules for Variable Names
var break = 3; // Raises a `SyntaxError: Unexpected token break`
var brake = 3; // This is fine, because "brake" is not a Reserved Keyword
var π = 3.1415926; // This works, but can be irritating to use
var = eval; // This works, but can be irritating to use
var numberOfDays = 3; // This is an ideal, readable camelCase variable name that isn't a reserved word!
How It Works
JavaScript needs to impose limits on variable names, otherwise you could accidentally override language features and functions
. Some other languages, such as PHP, get around this by forcing you to prefix every variable name with a $ sign; however, this becomes very limiting, so most languages including JavaScript simply disallow a small subset
of variable names. Some reserved words are not used in the language today, such as enum, but are intended to be included in the future and so become reserved as placeholders, to prevent use.
Solving Reference Errors When Declaring Variables Inside a Function’s Scope
Problem
You have attempted to declare a variable inside a function’s scope, but during runtime your code throws a
ReferenceError
, not letting you use that variable, or if you’re not using strict mode, your variables are undefined. Alternatively you’ve tried to assign a variable without using the var keyword. You have been presented with one of the following errors
:
ReferenceError: <name> is not defined
ReferenceError: assignment to undeclared variable <name>
ReferenceError: Can't find variable: <name>
Solution
JavaScript features something called “variable scopes
.” Every time a variable is declared, it is given a “scope.” Variables declared with the var keyword can only be used in the function containing them—that is to say, they are given the scope of that function. There is an additional global scope, which contains all variables that aren’t contained in functions. Variables cannot be used outside of their scope. The solution is to move them to a higher scope, i.e., out of the function. Look closely at the following examples.
The Code
function foo() { // This is a Function, which var a is wrapped in
var a = 3; // declare variable `a` inside foo()s scope.
}
console.log(a); // Raises `ReferenceError: a is not defined` (in strict mode, returns undefined otherwise)
foo();
console.log(a); // Raises `ReferenceError: a is not defined` (in strict mode, returns undefined otherwise)
var a = 3; // declare variable `a` in the global scope
function foo() {
a = 4; // reference the variable `a` from the global scope
}
console.log(a); // logs 3, because the variable `a` was declared in the global scope, outside of any function scopes
foo();
console.log(a); // logs 4, because the function foo(); took the globally scoped `a` and changed it to 4
var a = 3; // declare variable `a` in the global scope
function foo() {
var a = 4; // declare variable `a` in foo()s scope, without touching the globally scoped `a`
}
console.log(a); // logs 3, because the variable `a` was declared in the global scope, outside of any function scopes
foo();
console.log(a); // logs 3, because foo() declared its own `a` variable inside its own scope, and so modified the variable belonging to foo, not the global one
Listing 1-3.
Global Variables and the Notion of Scope
How It Works
Each function is given a “scope” or “sandbox,” so that it can manage its own variables without overriding or leaking
its own variables into the global scope. Variables inside of a function’s scope cannot be used outside of the function, or in other functions; this is very useful because it avoids conflicting variable names. If my function has a variable named length and so does yours, we don’t want to override each others variables with different values, so they are scoped for protection.
Function scoped variables also have an important use—they only live as long as the function runs, meaning they are cleaned from memory as soon as the function finishes. This is a very useful trick but can trip a lot of beginners up, so be careful and think hard about where you use your variables. The basic principle of scoping is similar to a “tree.” It begins with the root scope, and with each new function, a new “function scope” branch is created
, functions inside functions are branches of branches, and the whole thing goes on indefinitely. Consider the code in Listing 1-4.
function foo() {
var a = 1;
function bar() {
var b = 2;
function baz() {
console.log(a, b);
}
}
}
function bing() {
var a = 1;
function boo() {
console.log(a);
}
}
Listing 1-4.
A “Functional Scope” Example
This code can be expressed as a tree of scopes
(see Figure 1-1).
Figure 1-1.
A “functional scope” tree
of Listing 1-4
From the Figure 1-1, you can see the global scope holds the two functions:
foo() and bing()
. foo() has its own scope, which holds the a variable and the bar() function. bar() has its own scope, containing b and baz(). bing() has its own scope, containing a and boo().
It is important to note that the scope
has an upwards chain, meaning baz() can access its sibling, b, as well as its parents bar(), a, and foo(). Similarly, boo() can access its sibling a and its parent bing(). However, this chain does not flow in the opposite direction, so foo() cannot access bar()’s scope of b and baz() (it can, of course, access its own scope of a and bar()). This is a pretty contrived example, but real-world codebases can have much larger and more complex scope chains than this.
Assigning Variables with the Let Statement
Caution
The let statement is an ECMAScript 6 (ES6, the new standard of JavaScript) feature. Older browsers still in use, such as Internet Explorer 10 and below or Safari 7 and below, do not support this feature (they work with the older ECMAScript 5 or ES5 standard).
Problem
When using a variable, you want its life to be shorter than the functional scope. For example, you’d like the variables life to exist within an if statement.
Solution
Not only does JavaScript have a “functional scope,” it also has another level of scope, called “block scope
.” Block scoped variables offer the same semantics as function scoped variables, in that they are locked to a block, they cannot be accessed outside of a block
, and they are removed from memory as soon as the block finishes executing. A block is delimited by braces ({...}), and each new set of braces is a new block scope.
The Code
let a = 4; // The variable "a" has been declared and assigned to `4`
{
let b = 2; // The variable "b" has been declared and assigned to `2`
console.log(b); // Logs 2
}
if (a === 4) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
let a = 1; // The variable "a" has been redeclared in this block scope (the braces)
console.log(a); // Logs 1
}
console.log(b); // Raises a ReferenceError in strict mode, or logs undefined
console.log(a); // Logs 4, the `let a = 1` in the block scope above was only associated with that block scope
Listing 1-5.
Assigning Variables with the Let Statement
How It Works
The JavaScript interpreter will see the let keyword, followed by a set of variable names, with optionally assigned values. It then creates each of these keywords as a variable, for the life of the “block scope
.” It follows the same semantics as var, with the exception that it is tied to the block scope, not the function scope. Let variables also have another trick up their sleeve. When used in an if statement, or a for or while loop, the let variable is bound to the attached block, even though it is not inside the block itself. Take, for example, the code in Listing 1-6.
for (let i = 0, i < 4; ++i) {
console.log(i); // Logs 0, 1, 2, and 3
}
console.log(i); // Raises a ReferenceError in strict mode, or logs undefined
// Swap two variables:
var a = 1, b = 2;
{
let temp = a;
a = b;
b = temp;
}
console.log(a, b, typeof temp); // logs '2, 1, undefined'
Listing 1-6.
Letting Variables Block
This is useful because it provides another scoping layer for variables. Variables using the
var keyword
are accessible to the whole function’s scope. For temporary variables, such as the i in a loop (which get thrown away as soon as the loop is done) the variable would normally hang around until the end of the function’s life, which can be a nuisance. With a let variable this is very effectively solved, as the let variable
only exists for the life of the loop, and is then nicely cleaned up. You can also apply this by using blocks to encapsulate temporary variables, such as the second example in Listing 1-6.
Assigning Constants with the Const Statement
Caution
The const statement is an ECMAScript 6 (ES6
, the new standard of JavaScript) feature. Older browsers still in use, such as Internet Explorer 10 and below, Safari 7 and below, and Firefox 13 and below do not support this feature (they work to the older ECMAScript 5, or ES5 standard).
Problem
You want to use a variable, but you want to ensure that it is not overridden by a new value later on in the code.
Solution
The var and let statements certainly have their uses, but both are vulnerable to being unexpectedly overridden in the life of running code. Luckily, the const statement provides you with a way of declaring a variable that is immutable; that is, it will always be assigned to its initial value, and cannot be changed, cannot be “mutated”. It is a constant. One of the things to keep in mind is that objects can be updated. Constants only work with primitive values
.
The Code
var A = 3;
let B = 3;
const C = 3;
A = 4; B = 4; C = 4;
console.log(A, B, C); // Logs 4, 4, 3. `C`s value doesn't change, as it is a `const`.
Listing 1-7.
Assigning Constants with the Const Statement
How It Works
The JavaScript interpreter will see the const keyword, followed by a set of constant names, with assigned values
, and set those values to the constants as read-only (immutable)
. It follows the same semantics as let, including using block scoping just like let, with the exceptions that it can never be reassigned to a new value (it is immutable), and that it must be initially assigned to a value.
It is important to note that constants can never be declared without a value; this will cause a
SyntaxError
. Constants must always have a value assigned to them upon declaration.
const a; // Raises a SyntaxError (some browsers which have misinterpreted the ES6 spec may not raise this)
const a = 3; // Works as expected
Listing 1-8.
Attempting to Declare Constants Without Assigning Them
The spec is somewhat unclear about what precisely to do when a const is declared but not assigned, as a result, some browsers will not raise the SyntaxError, and the constant is permanently set to undefined, which is obviously pretty useless.
Creating and Using Literals
Caution
Template string literals
are an ECMAScript 6 (ES6, the new standard of JavaScript) feature. Older browsers still in use, such as Internet Explorer 11 and below, Safari 7 and below do not support this feature (they work to the older ECMAScript 5, or ES5 standard). In fact, at the time of writing only the Taceur Compiler tool could support template string literals. Check
http://kangax.github.io/es5-compat-table/es6/
for the current compatibility charts.
Problem
You want to create literal values of different types in JavaScript
; for example, you want to create a piece of text (string), or perhaps a number, or even a list of items (an array).
Solution
Literals are types of data
that can be defined without explicitly creating some kind of object or instance
. A literal can be a string (i.e., a piece of text), a decimal (base-10, 0-9), binary (base-2, 0-1), hexadecimal (base-16, 0-F), or octal (base-8, 0-7) number, a Boolean (true or false), an array (a list of other literals), an object (a named list of other literals), a regular expression (a complex text matching function), a function (a piece of code that can be repeatedly called), a template string (similar to a string, but replaces variable names with their values), as well as some standalone “primitive” values such as null and undefined. Each literal has a unique piece of syntax to denote its type, with perhaps the exception of decimal numbers.
The Code
'this is a string'; // A String literal (using Single Quotes)
"this is another string"; // A String literal (using Double Quotes)
true; // A Boolean literal
false; // A Boolean literal
3; // A Number literal
3.1415926; // Another Number literal
0b0101; // A Binary Number literal
0xFFF; // A Hexadecimal Number literal
0o888; // An Octal Number literal
[]; // An (empty) Array literal
[ 1, 2, 3, ]; // An Array literal populated with 3 Number literals
[ 'hello', 'world']; // An Array literal populated with 2 String literals
{}; // An (empty) Object literal
{ first: 1, second: 2 }; // An Object literal populated with 2 Number literals, named "first" and "second"
/abc/; // A Regular Expression literal
/^w{3,4}$/g; // A more complex Regular Expression literal
function () {}; // A Function literal
function foo() {}; // A named Function literal
null; // The null literal
undefined; // The undefined literal
`this is a template string`; // A Template String literal
`Hello #{name}
How are you?`; // A more complex Template String literal
Listing 1-9.
Literals
How It Works
The JavaScript interpreter will see each piece of unique syntax at the start of a literal; for example, a single/double quote for a string. It understands the specific rules around these and essentially creates that value as a literal instance of that type. The literals also borrow all properties from their “prototypes
,” for example everything you can do with new String('hello') you can also do with
hello
. Each of these literals can be assigned to a variable, or put inside an array or object. Each one has its own properties and attributes—you need to deal with each one in a different way. Chapters 3-15 guide you through how to utilize each of these types properly.
Creating Types Using Their Constructors
Problem
You want to be able to create literals more programmatically.
Solution
Some literals can also be created as instances from their constructor functions, with the new keyword. These instances allow for finer control of how they are created; however, it should be noted that some of these instances have very subtle differences to their literal counterparts. More about this later.
The Code
'hello'; // A String literal (using Single Quotes)
new String('hello'); // A String created from its constructor
[ 1, 2, 3 ]; // An Array literal with 3 Number literal values
new Array(1,2,3); // An Array created from its constructor
new Array(5); // An Array populated with 5 undefined values
/abc/; // A Regular Expression literal
new RegExp('abc'); // A Regular Expression created from its constructor
/^w{3,4}$/g; // A more complex Regular Expression literal
new RegExp('^\w{3,4}$', 'g'); // A more complex Regular Expression literal created from its constructor
function () { return 1 }; // A Function literal
new Function('return 1'); // A Function created from its constructor
{}; // An empty Object literal
new Object(); // An empty Object created from its constructor
Listing 1-10.
Literals versus Their Constructors
How It Works
JavaScript contains constructor functions, which relate to each literal. Some of these allow you to invoke them manually, which can be useful for creating these objects programmatically
, especially arrays and regular expressions. You should be aware that there are subtle differences between creating instances from the constructor functions and their literal counterparts, and you should always use the literal notation over constructors, unless you have a very specific reason for using the constructors. Constructors with the new keyword will actually create objects of that particular datatype, which is different than how literals work. This means, for example, typeof new String("hi") is equal to object, while typeof "hi" is equal to "string". While the Boolean(0) or Boolean("") will equal false, Boolean(new Number(0)) or Boolean(new String("")) will equal true. More details about the differences between these are featured in the later chapters for each datatype.
Determine If a Variable Has Been Defined Using an Equality Operator
Problem
You want to determine if the variable you have created is defined.
Solution
A variable is undefined when it has been declared but has not been assigned a value, or the assigned value is the undefined literal. Just imagine that when you are declaring variables that you’re making an entry in a dictionary. Every word (variable) that you use in JavaScript is undefined until you assign it a definition or value. The same holds true for function return values: if a function has no return statement, or if the return statement is used without specifying a value (i.e., return;), then the return value has not been defined and will therefore be the undefined literal.
The Code
var a; // The Variable "a" has been declared but it
// hasn't been assigned a definition.
var b = 5; // The variable "b" has been declared and
// assigned the number 5 as it's definition.
if (a === undefined) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("Variable 'a' is undefined");
} else {
console.log("Variable 'a' is defined");
}
if (b === undefined) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("Variable 'b' is undefined");
} else {
console.log("Variable 'b' is defined");
}
Listing 1-11.
Determining if a Variable Has Been Defined Using an Equality Operator
The output is:
Variable 'a' is undefined
Variable 'b' is defined
How It Works
Variable a has been declared but has not been assigned a value (a definition). A variable that has not been assigned a value is automatically assigned the undefined literal. Variable b has been declared and is defined as the numeric value 5. The first if statement
compares variable a to the undefined primitive value. Because variable a has not been defined, the comparison is true and the message Variable 'a' is undefined is displayed. On the other hand, variable b was defined so the same comparison to the undefined primitive value fails and the message Variable 'b' is defined is displayed.
Determining If a Variable Has Been Declared Using typeof( )
Problem
You test a variable to see if it is undefined using an equality operator and your script throws an exception because the variable has never been declared.
Solution
The typeof operator can be used to determine if a type is undefined. It returns a string indicating the type of the operand, but does not throw an error if the variable has never been declared.
The Code
// The declaration for variable a is commented out,
// therefore a has not been declared.
var a, b = 4;
if (typeof a === 'undefined') { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("Variable 'a' is undefined");
}
if (typeof b === 'undefined') { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("Variable 'b' is undefined");
}
Listing 1-12.
Determining If a Variable Has Been Declared Using typeof
The output is:
Variable 'a' is undefined
How It Works
Using the typeof operator is useful if a variable’s declaration status is not known, or for checking its value
if it has been declared. By asserting if a variable is undefined using typeof variable === 'undefined', you can safely see if a variable has a value, without causing a ReferenceError.
Determining If a Function Defines and Returns a Value
Problem
You are using a function to perform a task and need to determine if the return value has been defined, once the operation is complete.
Solution
All functions return a value whether the original developer intended it or not. If a value was defined and passed back to the function caller, it can be assigned to a variable or used directly. A function returns undefined if a value was not returned, or the return statement inside a function is empty.
The Code
// A function with an empty return-statement
// returns undefined
function function1() {
return;
}
// A function with no return-statement
// returns undefined
function function2() {
}
function function3() {
return 2 + 2;
}
function function4() {
return true;
}
function function5() {
return {};
}
var fn1 = function1();
console.log("Function1 returns: " + fn1); // undefined
var fn2 = function2();
console.log("Function2 returns: " + fn2); // undefined
var fn3 = function3();
console.log("Function3 returns: " + fn3); // 4
var fn4 = function4();
console.log("Function4 returns: " + fn4); // true
var fn5 = function5();
console.log("Function5 returns: " + fn5); // Object{}
// Test the return value of function1
if ( function1() === undefined ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log( "Function 1 returns undefined." );
}
else {
console.log( "Function 1 returns a value other than undefined." );
}
// Test the return value of function2
if ( function2() === undefined ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log( "Function 2 returns undefined." );
}
else {
console.log( "Function 2 returns a value other than undefined." );
}
// Test the return value of function3
if ( function3() === undefined ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log( "Function 3 returns undefined." );
}
else {
console.log( "Function 3 returns a value other than undefined." );
}
// Test the return value of function4
if ( function4() === undefined ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log( "Function 4 returns undefined." );
}
else {
console.log( "Function 4 returns a value other than undefined." );
}
// Test the return value of function5
if ( function5() === undefined ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log( "Function 5 returns undefined." );
}
else {
console.log( "Function 5 returns a value other than undefined." );
}
Listing 1-13.
Determining If a Function Defines and Returns a Value
The output is:
Function1 returns: undefined
Function2 returns: undefined
Function3 returns: 4
Function4 returns: true
Function5 returns: [object Object]
Function 1 returns undefined.
Function 2 returns undefined.
Function 3 returns a value other than undefined.
Function 4 returns a value other than undefined.
Function 5 returns a value other than undefined.
How It Works
Five functions are defined; the first two return undefined
. Function 1 explicitly returns undefined by using an empty return statement. Function 2 returns undefined implicitly by not using the return statement at all. Just as we can test the value of a variable, we can test the return value of a function using an equality operator. In many cases, functions’ return values can be treated like variables. A function’s return value can be printed to the console or used otherwise
. Note that because a function is already declared, its return value is implicitly declared too—so checking the return value of a function will never raise ReferenceError, unlike variables, which may if they’re undeclared.
Determining If a Defined Variable Has a Value Using Equality Operators
Problem
You know a variable has been previously defined but aren’t certain if its value is null or if it has another value.
Solution
You can use the equality operators to test for
null values
just like you test for undefined variables. null is an object and has only one value in JavaScript, null. A variable that is assigned null contains no valid data of the types Array, Boolean, String, Number, Date, Template String, or Object. When you want to declare a variable and initialize it, but do not want to give it value, just assign it the value null. This is useful if you need to declare a variable now but must wait for an operation to complete before assigning a value to the variable. Such cases may include number crunching or waiting for a response from a server. If the operation fails, the variable will remain null and this failure can be detected with code.
The Code
// myvar is undefined
var myvar = undefined;
if ( myvar === undefined) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("myvar is undefined");
}
if ( myvar === null) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("myvar is null");
}
// myvar is null
var myvar = null;
if ( myvar === undefined) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("myvar is undefined");
}
if ( myvar === null) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("myvar is null");
}
var myvar = null;
// Determine if myvar is null using the bang (!) operator
if ( !myvar ) {
console.log("The variable myvar is null or undefined");
} else {
console.log("The variable myvar is not null or undefined");
}
Listing 1-14.
Determining If a Defined Variable Has a Value Using Equality Operators
The output is:
myvar is undefined
myvar is null
The variable myvar is null or undefined
How It Works
Because null is falsey (it is equivalent to false when coerced to a Boolean), we can determine if a variable is null by using the bang operator (!)
to perform a logical NOT operation. In other words
, we’re asking if the variable myvar is “not false,” meaning true. This is the simplest (shortest code) technique for determining if a variable is null.
Performing Operations If a Defined Variable Has a Value
Problem
You need to perform different operations based on the value of a variable. You may need to test that a variable is strictly equal, simply equivalent, or strictly not equal to a value.
Solution
As we have done in previous sections, we will use comparison operators to detect the value of a variable and then branch to specific code blocks based on the value of the if statements.
The Code
var myNumber = 10;
// Determine if myNumber is equivalent to the number 10
if ( myNumber === 10 ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log( "myNumber equals 10");
}
else {
console.log( "myNumber is not equal to 10");
}
// Determine if myNumber is less than the number 10
if ( myNumber < 10 ) {
console.log( "myNumber is less than 10");
}
else {
console.log( "myNumber is equal to or greater than 10");
}
// Determine if myNumber is less than or equal to the number 10
if ( myNumber <= 10 ) {
console.log( "myNumber is less than or equal to 10");
}
else {
console.log( "myNumber is greater than 10");
}
// Determine if myNumber is greater than the number 10
if ( myNumber > 10 ) {
console.log( "myNumber is greater than 10");
}
else {
console.log( "myNumber is less than or equal to 10");
}
// Determine if myNumber is greater than or equal to the number 10
if ( myNumber >= 10 ) {
console.log( "myNumber is greater than or equal to 10");
}
else {
console.log( "myNumber is less than 10");
}
Listing 1-15.
Performing Operations If a Defined Variable Has a Value
The output is:
myNumber equals 10
myNumber is equal to or greater than 10
myNumber is less than or equal to 10
myNumber is greater than or equal to 10
How It Works
Flow control
of a script is very important to all programmers. Most scripts except the simplest of examples will have flow control of some kind. This example uses if statements to compare a variable to a fixed numeric value. If the comparison is true, the first code block below the comparison is executed. If the comparison is false, that block is not executed
, and the next block is compared. else blocks are executed if no other blocks in the whole if statement were true. We will take an in-depth look at expressions in Chapter 2.
What’s the Difference Between Null and Undefined ?
Problem
When working with an unfamiliar variable, you are uncertain if the variable is null or undefined and don’t know how to test the variable before working with it.
Solution
A variable is undefined only when the variable is declared but not assigned a value, or the variable has been explicitly assigned the undefined value. A variable is null only when it has been assigned the null value. This being the case, we can easily detect undefined and null variables as shown in the example. This makes null useful for explicitly representing a no-value variable, rather than a not-yet-defined variable, for example, in a function’s return statement.
The Code
var a;
var b = null;
if ( typeof a === 'undefined' ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log( "Variable a is undefined" );
}
if ( a === null ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log( "Variable a is null" );
}
if ( typeof b === 'undefined' ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log( "Variable b is undefined" );
}
if ( b === null ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log( "Variable b is null" );
}
Listing 1-16.
The Difference Between Null and Undefined
The output is:
Variable a is undefined
Variable b is null
How It Works
The
typeof operator
is used again as a more error-proof method of determining the type of a variable. The typeof operator
returns a string label for the variable type. The operator will return the string undefined for any variable that is truly undefined.
Coercing a Boolean Variable Using the Boolean Constructor
Problem
There are many cases where you will need to coerce an existing value into a Boolean true or false value for use in an if statement or other condition statements
.
Solution
Strings, numeric types, arrays, and objects can have an unlimited number of values, but the Boolean datatype can only have two: either true or
false
. A Boolean value indicates whether a condition, like those in an if statement, is true or not. The Boolean constructor can be used to convert any values passed into it to their Boolean equivalent.
The example in Listing 1-17 demonstrates coercion from various types into Boolean. Notice that we are not invoking a new Boolean—new Boolean()—we are instead using the Boolean constructor as a function—
Boolean()
—to coerce the given value into a Boolean primitive.
The Code
console.log( Boolean(-0) ); // logs false
console.log( Boolean(0) ); // logs false
console.log( Boolean(new Number(0)) ); // logs true
console.log( Boolean(1) ); // logs true
console.log( Boolean(NaN) ); // logs false
console.log( Boolean(-1) ); // logs true
console.log( Boolean(false) ); // logs false
console.log( Boolean(true) ); // logs true
console.log( Boolean(undefined) ); // logs false
console.log( Boolean(null) ); // logs false
console.log( Boolean(new String()) ); // logs true
console.log( Boolean("") ); // logs false
console.log( Boolean('a string') ); // logs true
console.log( Boolean("true") ); // logs true
console.log( Boolean("false") ); // logs true
console.log( Boolean(function () {}) ); // logs true
console.log( Boolean({}) ); // logs true
console.log( Boolean([]) ); // logs true
Listing 1-17.
Coercing a Boolean Variable Using a Boolean Constructor
How It Works
The Boolean constructor can take a single parameter and will convert it to a Boolean value internally based on the
ToBoolean internal function
, as part of the ECMAScript spec (specifically, section 7.1.2 of the ES6 spec, or 9.2 of the ES5 spec). If the value is 0, -0, null, false, NaN, undefined, or an empty string (''), the ToBoolean internal function will convert these to a value of false. The Boolean constructor
, when used without new will simply reuse the underlying ToBoolean internal logic, as does the bang operator (!) and other logical operators, such as AND (&&) and OR (||).
Determining If a Boolean Variable Is Initialized
Problem
You need to test a variable to determine if it is a Boolean or other datatype and determine if the Boolean variable has been initialized.
Solution
Using the typeof operator, we can determine the datatype of a variable. If the variable is a Boolean value, typeof will return the string 'boolean'.
The Code
var a = Boolean(true);
var b = false;
var c = "";
var d = new Date();
if ( typeof a === 'boolean' ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("a is a Boolean");
} else {
console.log("a is not a Boolean");
}
if ( typeof b === 'boolean' ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("b is a Boolean");
} else {
console.log("b is not a Boolean");
}
if ( typeof c === 'boolean' ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("c is a Boolean");
} else {
console.log("c is not a Boolean");
}
if ( typeof d === 'boolean' ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("d is a Boolean");
} else {
console.log("d is not a Boolean");
}
Listing 1-18.
Determining If a Boolean Variable Is Initialized
The output is:
a is a Boolean
b is a Boolean
c is not a Boolean
d is not a Boolean
How It Works
The typeof operator returns the string value Boolean for Boolean objects. To determine if a variable is a Boolean
, all we need to do is strictly compare the return value of the typeof operator to the string 'boolean'. Other datatypes, such as strings and numbers, return different strings that represent them.
Valid Representations of the False and True Values
Problem
You need to make a Boolean decision based on the value of a variable that is neither true nor false.
Solution
There are only two Boolean values: true and false. However, many different types such as numbers, strings, null, and undefined can be coerced to Boolean. if statements, switch statements, for statements, and while statements all coerce their given values to Booleans.
The Code
// If statements internally convert the given condition or value into Boolean values.
if (0) {
console.log( "0 is true");
} else {
console.log("0 is false");
}
if (-0) {
console.log( "-0 is true" );
} else {
console.log("-0 is false");
}
if (null) {
console.log( "null is true" );
} else {
console.log("null is false");
}
if (false) {
console.log( "false is true" );
} else {
console.log("false is false");
}
if (NaN) {
console.log( "NaN is true" );
} else {
console.log("NaN is false");
}
if (undefined) {
console.log( "undefined is true" );
} else {
console.log("undefined is false");
}
if ("") {
console.log( "Empty String is true" );
} else {
console.log("Empty String is false");
}
// Variable b holds the outcome of the comparison
// between Variable 'a' and the number 1.
var a = 1;
b = (a === 1); // true
if ( b ) {
console.log("Variable b is true");
} else {
console.log("Variable b is false");
}
// Examples of conditional or comparative expressions
var c = 1 + 2;
var d = null;
var e = a - 3;
var f = undefined;
if (c) {
console.log("Variable c is true");
} else {
console.log("Variable c is false");
}
if (d) {
console.log("Variable d is true");
} else {
console.log("Variable d is false");
}
if (e) {
console.log("Variable e is true");
} else {
console.log("Variable e is false");
}
if (f) {
console.log("Variable f is true");
} else {
console.log("Variable f is false");
}
Listing 1-19.
Valid Representations of the False and True Values
The output is:
0 is false
-0 is false
null is false
false is false
NaN is false
undefined is false
Empty String is false
Variable b is true
Variable c is true
Variable d is false
Variable e is true
Variable f is false
How It Works
Every statement that expects a condition
(if, switch, for, and while) will automatically coerce the given value into a Boolean (using the internal ToBoolean method described in Listing 1-14). If the Boolean value returned is false, the condition fails and the statement (if, switch, for, and while) is skipped. If the value is true then the block inside the statement is executed.
Coercing a String Using the String Constructor
Problem
You want to create a string representation of another value.
Solution
The string constructor takes a single parameter and will automatically convert that value into a string literal.
The Code
String("hello world"); // The String "hello world"
String(1); // The String "1"
String(false); // The String "false"
String(true); // The String "true"
String({}); // The String "[object Object]"
String([1,2,3]); // The String "1,2,3"
String(function foo() {}); // The String "function foo() {}"String(0b0101); // The String "5"
String(/abc/); // The String "/abc/"
String(undefined); // The String "undefined"
String(null); // The String "null"
// String casting can be overridden by providing the toString() method
String({ toString: function () { return 'hi!'; } }); // The String "hi!"
String({ toString: function () { return false; } }); // The String "false"
Listing 1-20.
Coercing a String Using the String Constructor
How It Works
Similarly to the Boolean constructor, the string constructor can also coerce values into its literal type. The ECMAScript spec contains an internal ToString function (ES6 section 7.1.12, ES5 section 9.8), which is used by the string constructor. It converts undefined to "undefined", null to "null", true to "true", false to "false" and number values to the string version of that number.
For other values, it checks to see if there is a toString method
attached to the value. If there is one, it will use the resulting value, coerced as a string, meaning the string constructor will always return a string. Arrays have a toString function on their prototype which simply calls Array.prototype.join(',')—this is explained in Chapter 6. Using the toString method is a powerful feature of JavaScript, as it allows you to create your own objects, which can coerce to a string in a customized way.
Determining If a Variable Is a String
Problem
You need to test a variable to determine if it is a string or other datatype.
Solution
Using the typeof operator, we can determine the datatype of a variable. If the variable is a string value, typeof will return the string "string".
The Code
var a = String("I'm a String Object");
var b = "I'm a string literal";
var c = 7;
var d = new Date();
if ( typeof a === 'string' ) {
console.log("a is a String");
} else {
console.log("a is not a String");
}
if ( typeof b === 'string' ) {
console.log("b is a String");
} else {
console.log("b is not a String");
}
if ( typeof c === 'string' ) {
console.log("c is a String");
} else {
console.log("c is not a String");
}
if ( typeof d === 'string' ) {
console.log("d is a String");
} else {
console.log("d is not a String");
}
Listing 1-21.
Determining If a Variable Is a String
The output is:
a is a String
b is a String
c is not a String
d is not a String
How It Works
The typeof operator returns the value "string" for string objects and literals. To determine if a variable is a string, all you need to do is compare the return value of the typeof operator to "
string
". Other datatypes such as objects and numbers return different strings that represent them.
Coercing a Numeric Value Using the Number Constructor
Problem
Sometimes you have numbers being represented as strings in your application. How can you convert these strings into actual number literals so you can use them effectively?
Solution
The number constructor takes a single parameter and will automatically convert a string parameter into a number.
The Code
var strNumber = "3.14159265";
var myNumber = Number(strNumber);
console.log("mynumber = " + myNumber);
console.log("mynumber type is " + typeof myNumber);
console.log("2 * mynumber = " + (2 * myNumber));
Listing 1-22.
Coercing a Numeric Value Using the Number Constructor
The output is:
mynumber = 3.14159265
mynumber type is number
2 * mynumber = 6.2831853
How It Works
The number constructor will attempt to convert its only parameter into a numeric value. If that is not possible
, the number object will be initialized to NaN (Not a Number).
Creating a Numeric Value Using Number Literals
Caution
Binary and octal notation are ECMAScript 6 (ES6) features. Older browsers still in use, such as Internet Explorer 11 and below and Safari 7 and below, do not support this feature (they work to the ECMAScript 5, or ES5 spec).
Problem
Not all numeric values in your application will come from your user or external data. In many cases you will need to use literal or hard-coded mathematical expressions
in your script.
Solution
JavaScript represents numbers using the double-precision 64-bit IEEE 754 floating-point standard. The JavaScript Number object represents all numbers as floating-point values, meaning there is no internal difference between Integers (whole numbers) and floating-point numbers.
Floating-point numbers
contain a decimal portion and may be expressed in scientific notation. Also known as "E notation
," this represents "times ten raised to the power of". For example, 1.02e3 means "1.02 times 10 raised to the power of 3,” or 1020.
Numbers can be written in decimal
, hexadecimal, binary, and octal. Hexadecimal and octal numbers can have negative values. Binary, hexadecimal, and octal numbers can only represent integer values; they cannot be written in E notation. When the JavaScript runtime finds one of these number literals, it will automatically convert it to the decimal, or base-10 representation (with no decimal places, of course).
Hexadecimal integers
(referred to as base-16 numbers) are notated by prefixing them with a 0x. They can contain digits 0 through 9, and letters A through F only. The letters A through F represent 10 through 15 in decimal (Base-10). Using letters other than A through F will raise a SyntaxError.
Octal integers
(referred to as Base-8 numbers) are notated by prefixing them with a 0o. They can contain digits 0 through 7 only. Using numbers outside of 0 through 7 will raise a SyntaxError.
Binary integers
(referred to as Base-2 numbers) are notated by prefixing them with 0b. They can only contain digits 0 and 1. Using numbers outside of 0 and 1 with a binary integer will raise a SyntaxError.
Hexadecimal, binary, and octal
are the most commonly used numeral systems, next to decimals, in computing. This is why they come built into the language. Examples of other popular numeral systems
that you may encounter in computing, but aren’t built into JavaScript, are Base-32 (Duotrigesimal) and Base-64 (Tetrasexagesimal). Refer to Table 1-2 for a handy guide on how each of the built-in JavaScript numerals convert.
Table 1-2.
Decimal, Hexadecimal, Octal, and Binary Conversion Chart
Decimal (Base-10) | Hexadecimal (Base-16) | Octal (Base-8) | Binary (Base-2) |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 1 | 1 | 1 |
2 | 2 | 2 | 10* |
3 | 3 | 3 | 11* |
4 | 4 | 4 | 100* |
5 | 5 | 5 | 101* |
6 | 6 | 6 | 110* |
7 | 7 | 7 | 111* |
8 | 8 | 10* | 1000* |
9 | 9 | 11* | 1001* |
10 | A | 12* | 1010* |
11 | B | 13* | 1011* |
12 | C | 14* | 1100* |
13 | D | 15* | 1101* |
14 | E | 16* | 1110* |
15 | F | 17* | 1111* |
The Code
// Basic arithmetic
var a = 1 + 1;
console.log( typeof a ); // number
console.log( "1 + 1 = " + a ); // 1 + 1 = 2
console.log(10 - 5.52 ); // 4.48
console.log(3.49 / .52 ); // 6.711538461538462
console.log(95.78 * 627 ); / 60054.06
// Comparing integer and floating-point values
console.log( 1 === 1.000 ); // true
console.log( typeof 1 === typeof 1.000 ); // true
// Scientific Notation
console.log( 1e1 ); // 10
console.log( 1e3 ); // 1000
console.log(1.51e-6 ); // 0.00000151
console.log( 1.7985e19 ); // 17985000000000000000
// Hexadecimal Notation
console.log( 0x01 ); // 1
console.log( 0x1a ); // 26
console.log( 0xbc ); // 188
console.log( 0xff ); // 255
// Octal Notation
console.log( 0o1 ); // 1
console.log( 0o32 ); // 26
console.log( 0o274 ); // 188
console.log( 0o377 ); // 255
// Octal Notation
console.log( 0b1 ); // 1
console.log( 0b11010 ); // 26
console.log( 0o10111100 ); // 2134592
console.log( 0o11111111 ); // 2396745
Listing 1-23.
Creating a Numeric Value Using Number Literals
How It Works
This simple overview is an introduction to the basics of numeric representation and manipulation
. To get the most out of number literals and the number object, make sure you read Chapter 4 to get an in-depth look at what JavaScript mathematics can really do. You will learn how to perform trigonometric, algebraic, calculus operations, and more.
Determining If a Defined Variable Is a Number
Problem
You need to test a variable to determine if it is a numeric value or another datatype.
Solution
Using the typeof operator, you can determine the datatype of a variable. If the variable is a Number value, typeof will return the string "number".
The Code
var a = Number(5.912);
var b = 4.7;
var c = "";
var d = new Date();
if ( typeof a === 'number' ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("a is a Number");
} else {
console.log("a is not a Number");
}
if ( typeof b === 'number' ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("b is a Number");
} else {
console.log("b is not a Number");
}
if ( typeof c === 'number' ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("c is a Number");
} else {
console.log("c is not a Number");
}
if ( typeof d === 'number' ) { // For more on the Strict Equality Operator (`===`), see Chapter 2-10
console.log("d is a Number");
} else {
console.log("d is not a Number");
}
Listing 1-24.
Determining If a Defined Variable Is a Number
The output is:
a is a Number
b is a Number
c is not a Number
d is not a Number
How It Works
The typeof operator returns the string value "
number"
for number objects. To determine if a variable is a number, all you need to do is compare the return value of the typeof operator to the string "number". Other datatypes such as strings and objects return different strings that represent them.
Dealing with NaN and Infinity
Caution
Number.isNaN() and Number.isFinite() are ES6 features. Older browsers still in use, such as Internet Explorer 11 and below and Safari 7 and below do not support this feature. However, they are supported on the global object, so for these browsers, you can use isNaN() or isFinite() (without the Number. prefix).
Problem
Sometimes you may encounter the literals `NaN` (Not a Number) and ±Infinity (`Infinity` or `-Infinity`). All of these values are the typeof number, and need extra checks to ensure the number you want is a finite number.
Solution
The number constructor has two static methods
(functions attached directly to the number constructor), Number.isNaN and Number.isFinite. Both return Booleans determining if the passed parameter is NaN or ±Infinity, respectively.
The Code
var a = NaN;
var b = Infinity;
var c = -Infinity;
var d = 3;
if ( Number.isNaN(a) ) {
console.log("a is a NaN (not a number)");
} else {
console.log("a is a real Number, not NaN");
}
if ( Number.isFinite(b) ) {
console.log("b is a finite Number");
} else {
console.log("b is not a finite Number, it is either +Infinity or -Infinity");
}
if ( Number.isFinite(c) ) {
console.log("c is a finite Number");
} else {
console.log("c is not a finite Number, it is either +Infinity or -Infinity");
}
if ( Number.isNaN(d) ) {
console.log("d is a NaN (not a number)");
} else {
console.log("d is a real Number, not NaN");
}
if ( Number.isFinite(d) ) {
console.log("d is a finite Number");
} else {
console.log("d is not a finite Number, it is either +Infinity or -Infinity");
}
Listing 1-25.
Dealing with NaN and Infinity
The output is:
a is a NaN (not a number)
b is not a finite Number, it is either +Infinity or -Infinity
c is not a finite Number, it is either +Infinity or -Infinity
d is a real Number, not NaN
d is a finite Number
How It Works
NaN and ±Infinity are Number objects
, which makes dealing with them difficult to detect; however, the two methods Number.isNaN() and Number.isFinite() are specifically built to detect these two edge cases. They are also available on the global object, meaning one can write, for example window.isNaN() or more simply isNaN(). It is especially important when taking user input as numbers, to check if the number is NaN.
Generating a Date Using the Date Object
Problem
You need to generate a date or timestamp for your application. You may need to pass this value back to the server or simply use it client-side.
Solution
It’s easy to create a timestamp with the date constructor; all you need to do is create an instance of the Date object without any parameters and assign it to a variable. The date constructor is also useful for recording timespans such as the length of time required for an operation to complete.
The Code
// The current date and time
// Wed Apr 10 2013 15:01:06 GMT-0400 (Eastern Daylight Time)
var today = new Date();
console.log(today);
// Thu Mar 14 2013 03:14:15 GMT-0400 (Eastern Daylight Time)
var dateOne = new Date("March 14, 2013 03:14:15");
console.log(dateOne);
// Wed Apr 10 2013 00:00:00 GMT-0400 (Eastern Daylight Time)
var dateTwo = new Date(2013,03,10);
console.log(dateTwo);
// Thu Mar 14 2013 03:14:15 GMT-0400 (Eastern Daylight Time)
var dateThree = new Date(2013,02,14,3,14,15);
console.log(dateThree);
// Working with Date components
var date = today.getDate(); // 13
var month = today.getMonth(); // 3
var year = today.getFullYear(); // 2013
console.log(date + "/" + month + "/" + year);
// Determine the duration of an event
var start = Date.now();
alert("Wait a few seconds then click OK");
var time = Date.now() - start;
console.log( "The operation took " + time + " milliseconds" );
Listing 1-26.
Generating a Date Using the Date Object
The output is:
Sun Dec 15 2013 23:46:08 GMT+0000 (GMT) // (this output may be different based on your timezone!)
Thu Mar 14 2013 03:14:15 GMT+0000 (GMT)
Wed Apr 10 2013 00:00:00 GMT+0100 (BST) // (this output may be different based on your timezone!)
Thu Mar 14 2013 03:14:15 GMT+0000 (GMT)
15/11/2013 // (this output may be different based on your locale!)
The operation took 1326 milliseconds
How It Works
The JavaScript Date object offers many powerful functions such as measuring a timespan, converting times from one time zone to another, adding and subtracting moments in time, and more
. Be sure to read Chapter 6 about dates and time, where the topic is covered in much more detail.
Generating a Date with a Date String
Problem
You have been given a date string from a server, client-side database or possibly generated from user input and need to manipulate it by using Date object methods.
Solution
The Date object constructor can accept a string that’s RFC 2822 (for example "Fri, 24 Jan 2014 21:18:23 +0000"), or RFC 3339 compliant (for example, "2014-01-24T21:18:23+00:00"). We’ll pass the date string into the date constructor to create a Date object instance.
The Code
var myDateString = "January 16, 1975 17:07:00";
var myDate = new Date(myDateString);
console.log(myDate);
myDate.setMonth(2);
console.log(myDate);
myDate.setHours(10);
console.log(myDate);
myDate.setMinutes(51);
console.log(myDate);
myDate.setSeconds(59);
console.log(myDate);
var myDateString = "1985-04-12T23:20:50.52Z";
var myDate = new Date(myDateString);
console.log(myDate);
myDate.setMonth(2);
console.log(myDate);
myDate.setHours(10);
console.log(myDate);
myDate.setMinutes(51);
console.log(myDate);
myDate.setSeconds(59);
console.log(myDate);
Listing 1-27.
Generating a Date with a Date String
The output is:
Thu Jan 16 1975 17:07:00 GMT+0000 (GMT)
Sun Mar 16 1975 17:07:00 GMT+0100 (GMT)
Sun Mar 16 1975 10:07:00 GMT+0100 (GMT)
Sun Mar 16 1975 10:51:00 GMT+0100 (GMT)
Sun Mar 16 1975 10:51:59 GMT+0100 (GMT)
Sat Apr 13 1985 00:20:50 GMT+0100 (BST)
Wed Mar 13 1985 00:20:50 GMT+0000 (GMT)
Wed Mar 13 1985 10:20:50 GMT+0000 (GMT)
Wed Mar 13 1985 10:51:50 GMT+0000 (GMT)
Wed Mar 13 1985 10:51:59 GMT+0000 (GMT)
How It Works
The JavaScript Date object will attempt to parse
many types of date strings, most notably RFC 3339 and RFC 2822 formatted date strings. This can be very useful as a tool for receiving dates from the server side. RFC 3339 strings are the recommended format for receiving and sending dates from the server side.
Determining If a Defined Variable Is a Date
Problem
You need to test a variable to determine if it is a Date object or another datatype.
Solution
We can’t use the typeof operator to return the variable’s type because typeof will return the string "object" for a Date instance (as it is not a literal). Instead we’ll use the instanceof operator to determine if a variable is an instance of the
Date object
.
The Code
var a = new Date();
var b = 3.14;
var c = "I'm a string";
if (a instanceof Date) {
console.log("a is a Date");
} else {
console.log("a is not a Date");
}
if (b instanceof Date) {
console.log("b is a Date");
} else {
console.log("b is not a Date");
}
if (c instanceof Date) {
console.log("c is a Date");
}
else {
console.log("c is not a Date");
}
Listing 1-28.
Determining If a Defined Variable Is a Date
The output is:
a is a Date
b is not a Date
c is not a Date
How It Works
The instanceof operator determines if a variable
is an instance of an object. In this example, various variables are tested to see if they are instances of the Date object. If a variable is an instance of the Date object, the instanceof operator returns true, otherwise false.
Creating an Object and Assigning Properties
Problem
You are required to create an object and give it some properties to use object-oriented practices in your code base.
Solution
Objects
are collections of methods and properties. A method is a function in an object. A property is one or more values or objects in an object. JavaScript supports its own internal objects, objects that you create, and host objects.
To create your own objects, you first create an object literal, and then populate it with properties and methods using the well-known dot notation.
The Code
// Create a House object
var House = {};
House.address = "123 Main Street, Podunkville, NC 28328";
House.area = 2800;
House.constructionDate = new Date(1991,0,16);
// The Architecture object contains structural information about the House
House.architecture = {};
House.architecture.floorPlan =
"http://upload.wikimedia.org/wikipedia/commons/b/b8/HouseFlrPlan.svg";
House.architecture.style = "American FourSquare";
House.architecture.doorsExternal = ["Living Room","Kitchen","Foyer"];
House.architecture.rooms = ["Kitchen","Living Room","Bathroom", "Guest Bedroom", "Secondary Bedroom", "Master Bedroom", "Master Bathroom"];
House.architecture.windows = ["Kitchen (2)","Living Room (2)","Bathroom (1)", "Guest Bedroom (1)", "Secondary Bedroom (1)", "Master Bedroom (1)", "Master Bathroom (1)"];
// House owner object
House.owner = {};
House.owner.name = "Matthew Stephen Skipper";
House.owner.phone = "123-456-7890";
// Display basic house data
console.log( "House at: " + House.address );
console.log( "Built on: " + House.constructionDate );
console.log( "Area: " + House.area + " square feet" );
// Display house owner data
console.log( "
House Owner" );
console.log( "Name: " + House.owner.name );
console.log( "Phone: " + House.owner.phone );
// Display house architecture data
console.log( "
House Architecture" );
console.log( "Area: " + House.area + " square feet" );
console.log( "Floor Plan URL: " + House.architecture.floorPlan );
console.log( "Style: " + House.architecture.style );
console.log( "External Doors: " + House.architecture.doorsExternal );
console.log( "Rooms: " + House.architecture.rooms );
console.log( "Windows: " + House.architecture.windows );
Listing 1-29.
Creating an Object and Assigning Properties
The output is:
House at: 123 Main Street, Podunkville, NC 28328
Built on: Wed Jan 16 1991 00:00:00 GMT-0500 (Eastern Standard Time)
Area: 2800 square feet
House Owner
Name: Matthew Stephen Skipper
Phone: 123-456-7890
House Architecture
Area: 2800 square feet
Floor Plan URL: http://upload.wikimedia.org/wikipedia/commons/b/b8/HouseFlrPlan.svg
Style: American FourSquare
External Doors: Living Room,Kitchen,Foyer
Rooms: Kitchen,Living Room,Bathroom,Guest Bedroom,Secondary Bedroom,Master Bedroom,Master Bathroom
Windows: Kitchen (2),Living Room (2),Bathroom (1),Guest Bedroom (1),Secondary Bedroom (1),Master Bedroom (1),Master Bathroom (1)
How It Works
The object created is a very simple representation of a house, its owner, and architecture. The house object contains five properties: address, area, constructionDate, architecture, and owner. The
architecture property
is another custom object with various properties about the house. The
owner property
is a third custom object containing data about the owner.
This house object is very simple and has no methods. However, it does show the basics of object creation and JavaScript object-oriented programming (OOP)
. Objects and object-oriented programming
are discussed in much more detail in Chapter 9.
Determining If a Defined Variable Is an Object
Problem
You need to test a variable to determine if it is an object or another datatype.
Solution
Using the typeof operator, we can determine the datatype of a variable. If the variable is an object, typeof will return the string "object".
The Code
var a = {};
var b = "I'm a string";
var c = 7;
if ( typeof a === 'object' ) {
console.log("a is an Object");
} else {
console.log("a is not an Object");
}
if ( typeof b === 'object' ) {
console.log("b is an Object");
} else {
console.log("b is not an Object");
}
if ( typeof c === 'object' ) {
console.log("c is an Object");
} else {
console.log("c is not an Object");
}
Listing 1-30.
Determining If a Defined Variable Is an Object
The output is:
a is an Object
b is not an Object
c is not an Object
How It Works
The typeof operator returns the string "
object"
for all objects derived from the built-in "object" object. Other datatypes such as strings and numbers return a string that represents them.
Determining If an Object Is an Instance
Problem
You need to determine if an object, such as a Date object, is an instance of a constructor, or an instance of the Object constructor; however, typeof returns the "object" value for all of these.
Solution
If you have an object, such as a Date object, and using typeof returns "object", but you still want to assert that the object is an instance of a constructor you can use the instanceof keyword.
The Code
var date = new Date();
var error = new Error();
var blob = new Blob();
var object = new Object();
typeof date; // Returns "object"
typeof error; // Returns "object"
typeof blob; // Returns "object"
if ( date instanceof Date ) {
console.log("date is a Date instance");
} else if ( date instanceof Error ) {
console.log("date is an Error instance");
} else if ( date instanceof Blob ) {
console.log("date is a Blob instance");
} else {
console.log("date is an unknown instance");
}
if ( error instanceof Date ) {
console.log("error is a Date instance");
} else if ( error instanceof Error ) {
console.log("error is an Error instance");
} else if ( error instanceof Blob ) {
console.log("error is a Blob instance");
} else {
console.log("error is an unknown instance");
}
if ( blob instanceof Date ) {
console.log("blob is a Date instance");
} else if ( blob instanceof Error ) {
console.log("blob is an Error instance");
} else if ( blob instanceof Blob ) {
console.log("blob is a Blob instance");
} else {
console.log("blob is an unknown instance");
}
if ( object instanceof Date ) {
console.log("object is a Date instance");
} else if ( object instanceof Error ) {
console.log("object is an Error instance");
} else if ( object instanceof Blob ) {
console.log("object is a Blob instance");
} else {
console.log("object is an unknown instance");
}
Listing 1-31.
Differences Between Objects and Instances
The output is:
date is a Date instance
error is an Error instance
blob is a Blob instance
object is an unknown instance
How It Works
The
instanceof operator
is a useful tool for detecting instances of constructors, especially when you want to determine the finer points of an objects inheritance. It is vitally important to remember that instanceof will not work on any literals, such as number literals or string literals. As a rule of thumb, instanceof only works on values that have a typeof of ”object”, so you could be ultra cautious by checking the typeof a value, followed by checking instanceof the object, only if the typeof is ”object”.
Determining an Object’s Direct Instance with the Constructor Property
Problem
Some objects are created from the result of a constructor (such as Date), but they also inherit from their parent constructor objects. For example, a Date object will return true for instanceof Date, but will also return true for instanceof Object. This becomes a problem when trying to find the direct descendant of an object.
Solution
Every object that has a constructor and can be created by using the new keyword will have a constructor property. This is set to the constructor function, so for example new Date()`s constructor property is Date.
The Code
var date = new Date();
var error = new Error();
var blob = new Blob();
var object = {};
if ( date.constructor === Date ) {
console.log("date is a Date instance");
} else if ( date.constructor === Error ) {
console.log("date is an Error instance");
} else if ( date.constructor === Blob ) {
console.log("date is a Blob instance");
} else {
console.log("date is an unknown instance");
}
if ( error.constructor === Date ) {
console.log("error is a Date instance");
} else if ( error.constructor === Error ) {
console.log("error is an Error instance");
} else if ( error.constructor === Blob ) {
console.log("error is a Blob instance");
} else {
console.log("error is an unknown instance");
}
if ( blob.constructor === Date ) {
console.log("blob is a Date instance");
} else if ( blob.constructor === Error ) {
console.log("blob is an Error instance");
} else if ( blob.constructor === Blob ) {
console.log("blob is a Blob instance");
} else {
console.log("blob is an unknown instance");
}
if ( object.constructor === Date ) {
console.log("object is a Date instance");
} else if ( object.constructor === Error ) {
console.log("object is an Error instance");
} else if ( object.constructor === Blob ) {
console.log("object is a Blob instance");
} else {
console.log("object is an unknown instance");
}
Listing 1-32.
Determining an Object’s Direct Instance with the Constructor Property
The output is:
date is a Date instance
error is an Error instance
blob is a Blob instance
object is an unknown instance
How It Works
The constructor property is very useful for determining the direct descendant of an object. It is also useful for getting the constructor itself, which can be useful for cloning an instance or making new instances
of the same type. It also illustrates the main difference between instanceof and constructor.
Determining If Something Is a Plain Object
Problem
You want to be able to assert that an object is not a descendant of a resulting constructor function, and instead asserting that an object is a plain object—one that was created using new Object() or an object literal ({}). instanceof will assert that the object is an instance of the object constructor. instanceof also asserts on any descendants of the object’s constructor such as the Date instances.
Solution
Just like in Listing 1-30, determining the direct descendant of an object should use the .constructor property. Determining if an object is a “plain” object (e.g., is not an instance of another constructor, such as date) requires the same process, even for object literals ({}).
The Code
var date = new Date();
var error = new Error();
var object = new Object();
var plainObject = {};
if ( date.constructor === Object ) {
console.log("date is a plain object");
} else {
console.log("date is not a plain object");
}
if ( error.constructor === Object ) {
console.log("error is a plain object");
} else {
console.log("error is not a plain object");
}
if ( object.constructor === Object ) {
console.log("object is a plain object");
} else {
console.log("object is not a plain object");
}
if ( plainObject.constructor === Object ) {
console.log("plainObject is a plain object");
} else {
console.log("plainObject is not a plain object");
}
Listing 1-33.
Determining If Something Is a Plain Object
The output is:
date is not a plain object
error is not a plain object
object is a plain object
plainObject is a plain object
How It Works
This is another important example of how the constructor property
can sometimes be more useful than instanceof. The instanceof property will “walk the prototype chain”; that is, it will check not only the direct descendant, but the descendant of that, and that, and that, and so on. This means objects like Date are instances of Object (in fact, nearly everything is), however “plain” objects are the only objects where the .constructor property should be Object.
Creating an Array and Assigning and Retrieving Values
Problem
You need to create a list of values and store them in an ordered manner.
Solution
Using arrays
is the best way to create an ordered list of values. Each value has a unique, numerical identifier and so, unlike objects, there is an explicit order to arrays.
The Code
var register = ['Annie', 'Cathy', 'Jessica', 'Sally'];
console.log(register[0]);
console.log(register[1]);
console.log(register[2]);
console.log(register[3]);
var places = ['First', 'Second', 'Third'];
console.log(places.length);
console.log(places[2]);
var bytes = new Array(2);
console.log(bytes.length);
console.log(bytes[0]);
Listing 1-34.
Creating an Array and Assigning and Retrieving Values
The output is:
Annie
Cathy
Jessica
Sally
3
Third
2
`undefined`
How It Works
Arrays
are ordered lists of values
. You can get to any individual value inside an array by using the staple-notation ([ and ]) with a numeric index of the key. The numerical index starts from 0 and counts up by 1 for each new value in the array. Arrays also include a .length property, which is set to the total number of items in the array. Arrays can be created with an initial length, by using the array constructor with the new keyword, and a length parameter. For example, new Array(3) will create an array with three undefined values in it.
Choosing Between Objects and Arrays
Problem
You are unsure when to use an object over an array, or are unsure of the merits of using either one.
Solution
Both arrays and objects store values against keys—they are “key-value stores”. The benefits of an array over an object are that the keys are predictable sequential numbers for each new item in the array, and that they explicitly maintain their sort order. Objects, on the other hand, do not have an explicit sort order and have unpredictable keys, they also cannot determine their length easily. An array’s key sequence is strictly sequential, so this has a side effect that if you create new values with large key numbers, the previous empty keys are backfilled to be undefined values.
The benefit of objects is that keys can be given a name decided by you, which can be very useful for object-oriented programming. Typically you would use objects for storing some kind of record, e.g., attributes about a person or place. You would likely use arrays for lists, perhaps a list of people or rankings. Refer to Table 1-3 for an object-array comparison.:
Table 1-3.
Objects versus Arrays Comparison
Objects | Arrays | |
---|---|---|
Key Types | String | Number |
Key Sequence
| Up to the user | Sequential numbers |
Key Predictability
| Low | High |
Lowest Key Value
| Unknown | 0 |
Highest Key Value
| Unknown | theArray.length - 1 |
Value
| Any | Any |
Duplicate Values Allowed
| Yes | Yes |
Duplicate Keys Allowed
| No | No |
Creating a Regular Expression Literal
Problem
You need to be able to match a string against a particular pattern and need a concise way to do it.
Solution
Using regular expressions
is the most powerful way to match patterns or test for patterns against a string value. It is a powerful tool that exists in many programming languages, including Ruby, C++11, Java, and Perl, and is even built into command-line tools
such as Awk and Sed.
The Code
var testString = 'hello world';
if ( /hello/.test(testString) ) {
console.log('testString contains "hello"!');
} else {
console.log('testString does not contain "hello"');
}
if ( /world/.test(testString) ) {
console.log('testString contains "world"!');
} else {
console.log('testString does not contain "world"');
}
var testStringMatch = testString.match(/(w+)+/g); // A complex pattern!
if ( testStringMatch ) {
console.log('testString contains ' + testStringMatch.length + ' words!');
} else {
console.log('testString does not contain any words');
}
Listing 1-35.
Creating a Regular Expression Literal
The output is:
testString contains "hello"!
testString contains "world"!
testString contains 2 words!
How It Works
Regular expressions are almost a miniature language alongside JavaScript (as well as many other languages), which allow for very powerful string finding and matching. The syntax is very complex, but with it comes a lot of power. Not only can you match parts of a string, as in the first two examples, but you can also match complex patterns
such as words, number patterns, word boundaries, character ranges, and a lot more. You can also extract parts of a string based on these patterns or replace parts of a string. Regular expressions are covered in extensive detail in Chapter 20.
Injecting Variables into a String with Template Literals
Caution
Template literals are an ECMAScript 6 (ES6) feature. Older browsers still in use, such as Internet Explorer 11 and below and Safari 7 and below, do not support this feature (they work off of the ECMAScript 5, or ES5 standard). In fact, at the time of writing only the Taceur Compiler tool could support template string literals. Check out
http://kangax.github.io/es5-compat-table/es6/
for the current compatibility charts.
Problem
You want to do variable substitution inside of a string.
Solution
JavaScript ES6 features template literals, which fix a wide range of issues with existing JavaScript strings, the biggest of which is injecting variables into strings. Template literals use backticks (` and `), whereas normal strings use quotes ("" or '').
The Code
var name = 'Bob';
console.log( 'Hello ' + name + '!' ); // The old way to do this, cumbersome and error prone
console.log( `Hello ${name}!` ); // Template Literals, shorter, more succinct, and less error prone
var otherName = 'Mary';
var thirdName = 'Jim';
console.log( 'Hello ' + otherName + ', how is ' + thirdName + '?' ); // Can get very messy
console.log( `Hello ${otherName}, how is ${thirdName}?` ); // Much cleaner
Listing 1-36.
Injecting Variables into a String with Template Literals
The output is:
Hello Bob!
Hello Bob!
Hello Mary, how is Jim?
Hello Mary, how is Jim?
How It Works
Template string literals
are specially tuned to let the JavaScript interpreter know that variable substitution needs to take place. Every time a template substitution (${}) is encountered, it will inject the known variable in its place, as you’d expect. The same scoping rules
for variables apply here, as they do everywhere else. Template string literals are much more powerful than simple variable substitution—they behave very differently from strings with regard to escaping characters, and can be passed into custom functions to build complex formatting and template engines. Template string literals are covered in Chapter 14 of this book.