© Adam Freeman 2018
Adam FreemanPro Angular 6https://doi.org/10.1007/978-1-4842-3649-9_5

5. JavaScript and TypeScript: Part 1

Adam Freeman1 
(1)
London, UK
 

In this chapter I provide a quick tour of the most important basic features of the JavaScript language as they apply to Angular development. I don’t have the space to describe JavaScript completely, so I have focused on the essentials that you’ll need to get up to speed and follow the examples in this book. In Chapter 6, I describe some of the more advanced JavaScript features that you will need and some of the additional features provided by TypeScript.

The JavaScript language is managed through a standard process that defines new features. Modern browsers have started to implement features from the ECMAScript 6 (also known as ES6) standard, and ECMAScript 7 (ES7) is making its way into service as I write this. The new standards broaden the features available to JavaScript developers and make using JavaScript more consistent with more conventional languages such as C# or Java.

Modern browsers update themselves, which means that a Google Chrome user, for example, is likely to have a recent release of the browser that implements at least some of the most recent JavaScript features. Sadly, older browsers that don’t update themselves are still in widespread use, which means you can’t rely on modern features being available for use in your application.

There are two ways to approach this problem. The first is to use only the core JavaScript features that you can rely on being present in the browsers that your application targets. The second is to use a compiler that processes your JavaScript files and converts them into code that can run on older browsers. It is the second approach that Angular takes and that I describe in this chapter. Table 5-1 summarizes this chapter.
Table 5-1

Chapter Summary

Problem

Solution

Listing

Create JavaScript functionality

Use JavaScript statements

5

Create groups of statements that are executed on command

Use functions

6, 7, 10–12

Define functions that can handle more or fewer arguments than parameters

Use default or rest parameters

8, 9

Express functions more concisely

Use arrow functions

13

Store values and objects for later use

Declare variables using the let or var keyword

14–16

Store basic data values

Use the JavaScript primitive types

17–20

Control the flow of JavaScript code

Use conditional statements

21

Determine whether two objects or values are the same

Use the quality and identity operators

22–23

Explicitly convert types

Use the to<type> methods

24–26

Store related objects or values together in sequence

Use an array

27–33

USING “PLAIN” JAVASCRIPT FOR ANGULAR

When Angular 2 was introduced, the use of TypeScript was optional, and it was possible to write Angular applications using plain JavaScript. The result was awkward and required some contorted code to re-create the effect of key TypeScript features, but it was possible, and Google provided a complete set of API documents for both TypeScript and plain JavaScript developers.

The support for working with plain JavaScript development has been reduced with each subsequent release, with the effect that there is no guidance for programmers who are reluctant to adopt TypeScript.

My advice is to embrace the complete Angular experience, even though it can take some time and effort to master TypeScript. The result will be a better development experience, containing code that is more concise, easier to read, and simpler to maintain. This is the approach I have taken in this book, and every example assumes that this is the path you are following.

Preparing the Example Project

To create the example project for this chapter, open a new command prompt, navigate to a convenient location, and run the command shown in Listing 5-1.

Tip

You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-angular-6 .

ng create JavaScriptPrimer
Listing 5-1

Creating the Example Project

This command creates a project called JavaScriptPrimer that is set up for Angular development. I don’t do any Angular development in this chapter, but I am going to use the Angular development tools as a convenient way to demonstrate different JavaScript and TypeScript features. To prepare, I replaced the contents of the main.ts file in the src folder with the single JavaScript statement shown in Listing 5-2.

Tip

Pay attention to the extension of the file. Even though this chapter uses only JavaScript features, it relies on the TypeScript compiler to convert them into code that will run in any browser. That means the .ts file must be used, which then allows the TypeScript compiler to create the corresponding .js file that will be used by the browser.

console.log("Hello");
Listing 5-2

Replacing the Contents of the main.ts File in the src Folder

Run the command shown in Listing 5-3 in the JavaScriptPrimer folder to start the Angular development compiler and HTTP server.
ng serve --port 3000 --open
Listing 5-3

Starting the Development Tools

A new browser tab or window will open but will be empty, as shown in Figure 5-1, because I replaced the contents of the main.ts file and the browser has nothing to display.
../images/421542_3_En_5_Chapter/421542_3_En_5_Fig1_HTML.jpg
Figure 5-1

Running the example application

All the results for the examples in this chapter are displayed in the browser’s JavaScript console. Open the browser’s F12 developer tools (so called because they are typically opened by pressing the F12 key) and look at the Console tab, which is shown in Figure 5-2.
../images/421542_3_En_5_Chapter/421542_3_En_5_Fig2_HTML.jpg
Figure 5-2

The Google Chrome JavaScript console

The JavaScript console shows the result of the call to the console.log function from Listing 5-2. Rather than show a screenshot of the browser’s JavaScript console for each example, I’ll just show the text result, like this:
Hello

Understanding the Basic Workflow

Writing the word Hello to the JavaScript console is a simple example, but there is a lot going on behind the scenes. To get a sense of the development workflow, add the statement shown in Listing 5-4 to the main.ts file.
console.log("Hello");
console.log("Apples");
Listing 5-4

Adding a Statement in the main.ts File in the src Folder

When you save the change to the main.ts file, the following process occurs:
  1. 1.

    The TypeScript compiler will detect the change to the main.ts file and compile it to generate a new main.js file that can run in any browser. The code that is produced is combined with the other JavaScript code produced by the compiler into a single file called a bundle.

     
  2. 2.

    The development HTTP server detects the change to the bundle file and signals the browser to reload the HTML document.

     
  3. 3.

    The browser reloads the HTML document and starts processing the elements it contains. It loads the JavaScript files specified by the script elements in the HTML document, including one that specifies the bundle file that contains the statements from the main.ts file.

     
  4. 4.

    The browser executes the statements that were originally in the main.ts file, which writes out two messages to the browser’s JavaScript console.

     
The overall result is that you will see the following messages displayed:
Hello
Apples

This may seem like a large number of steps for a simple application, but this process allows TypeScript features to be used and automatically takes care of detecting changes, running the compiler, and updating the browser.

Using Statements

The basic JavaScript building block is the statement. Each statement represents a single command, and statements are usually terminated by a semicolon (;). The semicolon is optional, but using them makes your code easier to read and allows for multiple statements on a single line. In Listing 5-5, I have added a pair of statements to the JavaScript file.
console.log("Hello");
console.log("Apples");
console.log("This is a statement");
console.log("This is also a statement");
Listing 5-5

Adding JavaScript Statements in the main.ts File in the src Folder

The browser executes each statement in turn. In this example, all the statements simply write messages to the console. The results are as follows:
Hello
Apples
This is a statement
This is also a statement

Defining and Using Functions

When the browser receives JavaScript code, it executes the statements it contains in the order in which they have been defined. This is what happened in the previous example. The browser loader loaded the main.js file, and the statements it contains were executed one by one, all of which wrote a message to the console.

You can also package statements into a function, which won’t be executed until the browser encounters a statement that invokes the function, as shown in Listing 5-6.
let myFunc = function () {
    console.log("This is a statement");
};
myFunc();
Listing 5-6

Defining a JavaScript Function in the main.ts File in the src Folder

Defining a function simple: use the let keyword followed by the name you want to give the function, followed by the equal sign (=) and the function keyword, followed by parentheses (the ( and ) characters). The statements you want the function to contain are enclosed between braces (the { and } characters).

In the listing, I used the name myFunc, and the function contains a single statement that writes a message to the JavaScript console. The statement in the function won’t be executed until the browser reaches another statement that calls the myFunc function, like this:
...
myFunc();
...
Executing the statement in the function produces the following output:
This is a statement

Other than demonstrating how functions are defined, this example isn’t especially useful because the function is invoked immediately after it has been defined. Functions are much more useful when they are invoked in response to some kind of change or event, such as user interaction.

THE OTHER WAY TO DEFINE FUNCTIONS

There are two ways in which you can define functions in JavaScript. The approach I used in Listing 5-6 is known as a function expression. The same function can also be defined like this:
...
function myFunc() {
    console.log("This is a statement");
}
...
This is known as a function declaration. The result is the same: a function called myFunc that writes a message to the console. The difference is how the functions are processed by the browser when a JavaScript file is loaded. Function declarations are processed before the code in a JavaScript file is executed, which means you can use a statement that calls a function before it is defined, like this:
...
myFunc();
function myFunc() {
    console.log("This is a statement");
}
...
This works because the browser finds the function declaration when it parses the JavaScript file and sets up the function before the remaining statements are executed, a process known as function hoisting. Function expressions, however, are not subject to hoisting, which means that this code will not work:
...
myFunc();
let myFunc = function() {
    console.log("This is a statement");
};
...

This code will generate an error reporting that myFunc is not a function. Developers who are new to JavaScript tend to prefer using function declarations because the syntax is more consistent with languages like C# or Java. The technique you use is entirely up to you, although you should aim to be consistent throughout your project to make your code easier to understand.

Defining Functions with Parameters

JavaScript allows you to define parameters for functions, as shown in Listing 5-7.
let myFunc = function(name, weather) {
    console.log("Hello " + name + ".");
    console.log("It is " + weather + " today");
};
myFunc("Adam", "sunny");
Listing 5-7

Defining Functions with Parameters in the main.ts File in the src Folder

I added two parameters to the myFunc function, called name and weather. JavaScript is a dynamically typed language, which means you don’t have to declare the data type of the parameters when you define the function. I’ll come back to dynamic typing later in the chapter when I cover JavaScript variables. To invoke a function with parameters, you provide values as arguments when you invoke the function, like this:
...
myFunc("Adam", "sunny");
...
The results from this listing are as follows:
Hello Adam.
It is sunny today

Using Default and Rest Parameters

The number of arguments you provide when you invoke a function doesn’t need to match the number of parameters in the function. If you call the function with fewer arguments than it has parameters, then the value of any parameters you have not supplied values for is undefined, which is a special JavaScript value. If you call the function with more arguments than there are parameters, then the additional arguments are ignored.

The consequence of this is that you can’t create two functions with the same name and different parameters and expect JavaScript to differentiate between them based on the arguments you provide when invoking the function. This is called polymorphism, and although it is supported in languages such as Java and C#, it isn’t available in JavaScript. Instead, if you define two functions with the same name, then the second definition replaces the first.

There are two ways that you can modify a function to respond to a mismatch between the number of parameters it defines and the number of arguments used to invoke it. Default parameters deal with the situation where there are fewer arguments than parameters, and they allow you to provide a default value for the parameters for which there are no arguments, as shown in Listing 5-8.
let myFunc = function (name, weather = "raining") {
    console.log("Hello " + name + ".");
    console.log("It is " + weather + " today");
};
myFunc("Adam");
Listing 5-8

Using a Default Parameter in the main.ts File in the src Folder

The weather parameter in the function has been assigned a default value of raining, which will be used if the function is invoked with only one argument, producing the following results:
Hello Adam.
It is raining today
Rest parameters are used to capture any additional arguments when a function is invoked with additional arguments, as shown in Listing 5-9.
let myFunc = function (name, weather, ...extraArgs) {
    console.log("Hello " + name + ".");
    console.log("It is " + weather + " today");
    for (let i = 0; i < extraArgs.length; i++) {
        console.log("Extra Arg: " + extraArgs[i]);
    }
};
myFunc("Adam", "sunny", "one", "two", "three");
Listing 5-9

Using a Rest Parameter in the main.ts File in the src Folder

The rest parameter must be the last parameter defined by the function, and its name is prefixed with an ellipsis (three periods, ...). The rest parameter is an array to which any extra arguments will be assigned. In the listing, the function prints out each extra argument to the console, producing the following results:
Hello Adam.
It is sunny today
Extra Arg: one
Extra Arg: two
Extra Arg: three

Defining Functions That Return Results

You can return results from functions using the return keyword. Listing 5-10 shows a function that returns a result.
let myFunc = function(name) {
    return ("Hello " + name + ".");
};
console.log(myFunc("Adam"));
Listing 5-10

Returning a Result from a Function in the main.ts File in the src Folder

This function defines one parameter and uses it to produce a result. I invoke the function and pass the result as the argument to the console.log function, like this:
...
console.log(myFunc("Adam"));
...
Notice that you don’t have to declare that the function will return a result or denote the data type of the result. The result from this listing is as follows:
Hello Adam.

Using Functions As Arguments to Other Functions

JavaScript functions can be passed around as objects, which means you can use one function as the argument to another, as demonstrated in Listing 5-11.
let myFunc = function (nameFunction) {
    return ("Hello " + nameFunction() + ".");
};
console.log(myFunc(function () {
    return "Adam";
}));
Listing 5-11

Using a Function as an Arguments to Another Function in the main.ts File

The myFunc function defines a parameter called nameFunction that it invokes to get the value to insert into the string that it returns. I pass a function that returns Adam as the argument to myFunc, which produces the following output:
Hello Adam.
Functions can be chained together, building up more complex functionality from small and easily tested pieces of code, as shown in Listing 5-12.
let myFunc = function (nameFunction) {
    return ("Hello " + nameFunction() + ".");
};
let printName = function (nameFunction, printFunction) {
    printFunction(myFunc(nameFunction));
}
printName(function () { return "Adam" }, console.log);
Listing 5-12

Chaining Functions Calls in the main.ts File in the src Folder

This example produces the same result as Listing 5-11.

Using Arrow Functions

Arrow functions—also known as fat arrow functions or lambda expressions—are an alternative way of defining functions and are often used to define functions that are used only as arguments to other functions. Listing 5-13 replaces the functions from the previous example with arrow functions.
let myFunc = (nameFunction) => ("Hello " + nameFunction() + ".");
let printName = (nameFunction, printFunction) => printFunction(myFunc(nameFunction));
printName(function () { return "Adam" }, console.log);
Listing 5-13

Using Arrow Functions in the main.ts File in the src Folder

These functions perform the same work as the ones in Listing 5-12. There are three parts to an arrow function: the input parameters, then an equal sign and a greater-than sign (the “arrow”), and finally the function result. The return keyword and curly braces are required only if the arrow function needs to execute more than one statement. There are more examples of arrow functions later in this chapter.

Using Variables and Types

The let keyword is used to declare variables and, optionally, assign a value to the variable in a single statement. Variables declared with let are scoped to the region of code in which they are defined, as shown in Listing 5-14.
let messageFunction = function (name, weather) {
    let message = "Hello, Adam";
    if (weather == "sunny") {
        let message = "It is a nice day";
        console.log(message);
    } else {
        let message = "It is " + weather + " today";
        console.log(message);
    }
    console.log(message);
}
messageFunction("Adam", "raining");
Listing 5-14

Using let to Declare Variables in the main.ts File in the src Folder

In this example, there are three statements that use the let keyword to define a variable called message. The scope of each variable is limited to the region of code that it is defined in, producing the following results:
It is raining today
Hello, Adam
This may seem like an odd example, but there is another keyword that can be used to declare variables: var. The let keyword is a relatively new addition to the JavaScript specification that is intended to address some oddities in the way var behaves. Listing 5-15 takes the example from Listing 5-14 and replaces let with var.
let messageFunction = function (name, weather) {
    var message = "Hello, Adam";
    if (weather == "sunny") {
        var message = "It is a nice day";
        console.log(message);
    } else {
        var message = "It is " + weather + " today";
        console.log(message);
    }
    console.log(message);
}
messageFunction("Adam", "raining");
Listing 5-15

Using var to Declare Variables in the main.ts File in the src Folder

When you save the changes in the listing, you will see the following results:
It is raining today
It is raining today

The problem is that the var keyword creates variables whose scope is the containing function, which means that all the references to message are referring to the same variable. This can cause unexpected results for even experienced JavaScript developers and is the reason that the more conventional let keyword was introduced.

USING LET AND CONST

The let keyword is used to define a variable, and the const keyword is used to define a constant value that will not change. It is good practice to use the const keyword for any value that you don’t expect to modify so that you receive an error if any modifications are attempted. This is a practice that I rarely follow, however—in part because I am still adapting to not using the var keyword and in part because I write code in a range of languages and there are some features that I avoid because they trip me up when I switch from one to another. If you are new to JavaScript, then I recommend trying to use const and let correctly and avoiding following my poor behavior.

Using Variable Closure

If you define a function inside another function—creating inner and outer functions—then the inner function is able to access the variables of the outer function, using a feature called closure, as demonstrated in Listing 5-16.
let myFunc = function(name) {
    let myLocalVar = "sunny";
    let innerFunction = function () {
        return ("Hello " + name + ". Today is " + myLocalVar + ".");
    }
    return innerFunction();
};
console.log(myFunc("Adam"));
Listing 5-16

Using Variable Closure in the main.ts File in the src Folder

The inner function in this example is able to access the local variables of the outer function, including its name parameter. This is a powerful feature that means you don’t have to define parameters on inner functions to pass around data values, but caution is required because it is easy to get unexpected results when using common variable names like counter or index, where you may not realize that you are reusing a variable name from the outer function. This example produces the following results:
Hello Adam. Today is sunny.

Using the Primitive Types

JavaScript defines a basic set of primitive types: string, number, and boolean. This may seem like a short list, but JavaScript manages to fit a lot of flexibility into these three types.

Tip

I am simplifying here. There are three other primitives that you may encounter. Variables that have been declared but not assigned a value are undefined, while the null value is used to indicate that a variable has no value, just as in other languages. The final primitive type is Symbol, which is an immutable value that represents a unique ID but that is not widely used at the time of writing.

Working with Booleans

The boolean type has two values: true and false. Listing 5-17 shows both values being used, but this type is most useful when used in conditional statements, such as an if statement. There is no console output from this listing.
let firstBool = true;
let secondBool = false;
Listing 5-17

Defining boolean Values in the main.ts File in the src Folder

Working with Strings

You define string values using either the double quote or single quote characters, as shown in Listing 5-18.
let firstString = "This is a string";
let secondString = 'And so is this';
Listing 5-18

Defining string Variables in the main.ts File in the src Folder

The quote characters you use must match. You can’t start a string with a single quote and finish with a double quote, for example. There is no output from this listing. JavaScript provides string objects with a basic set of properties and methods, the most useful of which are described in Table 5-2.
Table 5-2

Useful string Properties and Methods

Name

Description

length

This property returns the number of characters in the string.

charAt(index)

This method returns a string containing the character at the specified index.

concat(string)

This method returns a new string that concatenates the string on which the method is called and the string provided as an argument.

indexOf(term, start)

This method returns the first index at which term appears in the string or -1 if there is no match. The optional start argument specifies the start index for the search.

replace(term, newTerm)

This method returns a new string in which all instances of term are replaced with newTerm.

slice(start, end)

This method returns a substring containing the characters between the start and end indices.

split(term)

This method splits up a string into an array of values that were separated by term.

toUpperCase()

toLowerCase()

These methods return new strings in which all the characters are uppercase or lowercase.

trim()

This method returns a new string from which all the leading and trailing whitespace characters have been removed.

Using Template Strings
A common programming task is to combine static content with data values to produce a string that can be presented to the user. The traditional way to do this is through string concatenation, which is the approach I have been using in the examples so far in this chapter, as follows:
...
let message = "It is " + weather + " today";
...
JavaScript also supports template strings, which allow data values to be specified inline, which can help reduce errors and result in a more natural development experience. Listing 5-19 shows the use of a template string.
let messageFunction = function (weather) {
    let message = `It is ${weather} today`;
    console.log(message);
}
messageFunction("raining");
Listing 5-19

Using a Template String in the main.ts File

Template strings begin and end with backticks (the ` character), and data values are denoted by curly braces preceded by a dollar sign. This string, for example, incorporates the value of the weather variable into the template string:
...
let message = `It is ${weather} today`;
...
This example produces the following output:
It is raining today

Working with Numbers

The number type is used to represent both integer and floating-point numbers (also known as real numbers). Listing 5-20 provides a demonstration.
let daysInWeek = 7;
let pi = 3.14;
let hexValue = 0xFFFF;
Listing 5-20

Defining number Values in the main.ts File in the src Folder

You don’t have to specify which kind of number you are using. You just express the value you require, and JavaScript will act accordingly. In the listing, I have defined an integer value, defined a floating-point value, and prefixed a value with 0x to denote a hexadecimal value.

Using JavaScript Operators

JavaScript defines a largely standard set of operators. I’ve summarized the most useful in Table 5-3.
Table 5-3

Useful JavaScript Operators

Operator

Description

++, --

Pre- or post-increment and decrement

+, -, *, /, %

Addition, subtraction, multiplication, division, remainder

<, <=, >, >=

Less than, less than or equal to, more than, more than or equal to

==, !=

Equality and inequality tests

===, !==

Identity and nonidentity tests

&&, ||

Logical AND and OR (|| is used to coalesce null values)

=

Assignment

+

String concatenation

?:

Three-operand conditional statement

Using Conditional Statements

Many of the JavaScript operators are used in conjunction with conditional statements. In this book, I tend to use the if/else and switch statements. Listing 5-21 shows the use of both, which will be familiar if you have worked with pretty much any programming language.
let name = "Adam";
if (name == "Adam") {
    console.log("Name is Adam");
} else if (name == "Jacqui") {
    console.log("Name is Jacqui");
} else {
    console.log("Name is neither Adam or Jacqui");
}
switch (name) {
    case "Adam":
        console.log("Name is Adam");
        break;
    case "Jacqui":
        console.log("Name is Jacqui");
        break;
    default:
        console.log("Name is neither Adam or Jacqui");
        break;
}
Listing 5-21

Using the if/else and switch Conditional Statements in the main.ts File

The results from the listing are as follows:
Name is Adam
Name is Adam

The Equality Operator vs. the Identity Operator

The equality and identity operators are of particular note. The equality operator will attempt to coerce (convert) operands to the same type to assess equality. This is a handy feature, as long as you are aware it is happening. Listing 5-22 shows the equality operator in action.
let firstVal = 5;
let secondVal = "5";
if (firstVal == secondVal) {
    console.log("They are the same");
} else {
    console.log("They are NOT the same");
}
Listing 5-22

Using the Equality Operator in the main.ts File in the src Folder

The output from this script is as follows:
They are the same
JavaScript is converting the two operands into the same type and comparing them. In essence, the equality operator tests that values are the same irrespective of their type. To help guard against this kind of error, the TypeScript compiler will generate a warning, although it will still generate the JavaScript code since this type of comparison is legal:
Operator '==' cannot be applied to types 'number' and 'string'.
If you want to test to ensure that the values and the types are the same, then you need to use the identity operator (===, three equal signs, rather than the two of the equality operator), as shown in Listing 5-23.
let firstVal = 5;
let secondVal = "5";
if (firstVal === secondVal) {
    console.log("They are the same");
} else {
    console.log("They are NOT the same");
}
Listing 5-23

Using the Identity Operator in the main.ts File in the src Folder

In this example, the identity operator will consider the two variables to be different. This operator doesn’t coerce types. The result from this script is as follows:
They are NOT the same

Explicitly Converting Types

The string concatenation operator (+) has a higher precedence than the addition operator (also +), which means JavaScript will concatenate variables in preference to adding. This can cause confusion because JavaScript will also convert types freely to produce a result—and not always the result that is expected, as shown in Listing 5-24.
let myData1 = 5 + 5;
let myData2 = 5 + "5";
console.log("Result 1: " + myData1);
console.log("Result 2: " + myData2);
Listing 5-24

String Concatenation Operator Precedence in the main.ts File

The result from this script is as follows:
Result 1: 10
Result 2: 55

The second result is the kind that causes confusion. What might be intended to be an addition operation is interpreted as string concatenation through a combination of operator precedence and over-eager type conversion. To avoid this, you can explicitly convert the types of values to ensure you perform the right kind of operation, as described in the following sections.

Converting Numbers to Strings

If you are working with multiple number variables and want to concatenate them as strings, then you can convert the numbers to strings with the toString method, as shown in Listing 5-25.
let myData1 = (5).toString() + String(5);
console.log("Result: " + myData1);
Listing 5-25

Using the number.toString Method in the main.ts File in the src Folder

Notice that I placed the numeric value in parentheses, and then I called the toString method. This is because you have to allow JavaScript to convert the literal value into a number before you can call the methods that the number type defines. I have also shown an alternative approach to achieve the same effect, which is to call the String function and pass in the numeric value as an argument. Both of these techniques have the same effect, which is to convert a number to a string, meaning that the + operator is used for string concatenation and not addition. The output from this script is as follows:
Result: 55
There are some other methods that allow you to exert more control over how a number is represented as a string. I briefly describe these methods in Table 5-4. All of the methods shown in the table are defined by the number type.
Table 5-4

Useful Number-to-String Methods

Method

Description

toString()

This method returns a string that represents a number in base 10.

toString(2)toString(8)toString(16)

This method returns a string that represents a number in binary, octal, or hexadecimal notation.

toFixed(n)

This method returns a string representing a real number with the n digits after the decimal point.

toExponential(n)

This method returns a string that represents a number using exponential notation with one digit before the decimal point and n digits after.

toPrecision(n)

This method returns a string that represents a number with n significant digits, using exponential notation if required.

Converting Strings to Numbers

The complementary technique is to convert strings to numbers so that you can perform addition rather than concatenation. You can do this with the Number function, as shown in Listing 5-26.
let firstVal = "5";
let secondVal = "5";
let result = Number(firstVal) + Number(secondVal);
console.log("Result: " + result);
Listing 5-26

Converting Strings to Numbers in the main.ts File in the src Folder

The output from this script is as follows:
Result: 10
The Number function is strict in the way that it parses string values, but there are two other functions you can use that are more flexible and will ignore trailing non-number characters. These functions are parseInt and parseFloat. I have described all three methods in Table 5-5.
Table 5-5

Useful String to Number Methods

Method

Description

Number(str)

This method parses the specified string to create an integer or real value.

parseInt(str)

This method parses the specified string to create an integer value.

parseFloat(str)

This method parses the specified string to create an integer or real value.

Working with Arrays

JavaScript arrays work like arrays in most other programming languages. Listing 5-27 shows how you can create and populate an array.
let myArray = new Array();
myArray[0] = 100;
myArray[1] = "Adam";
myArray[2] = true;
Listing 5-27

Creating and Populating an Array in the main.ts File in the src Folder

I have created a new array by calling new Array(). This creates an empty array, which I assign to the variable myArray. In the subsequent statements, I assign values to various index positions in the array. (There is no console output from this listing.)

There are a couple of things to note in this example. First, I didn’t need to declare the number of items in the array when I created it. JavaScript arrays will resize themselves to hold any number of items. The second point is that I didn’t have to declare the data types that the array will hold. Any JavaScript array can hold any mix of data types. In the example, I have assigned three items to the array: a number, a string, and a boolean.

Using an Array Literal

The array literal style lets you create and populate an array in a single statement, as shown in Listing 5-28.
let myArray = [100, "Adam", true];
Listing 5-28

Using the Array Literal Style in the main.ts File in the src Folder

In this example, I specified that the myArray variable should be assigned a new array by specifying the items I wanted in the array between square brackets ([ and ]). (There is no console output from this listing.)

Reading and Modifying the Contents of an Array

You read the value at a given index using square braces ([ and ]), placing the index you require between the braces, as shown in Listing 5-29.
let myArray = [100, "Adam", true];
console.log("Index 0: " + myArray[0]);
Listing 5-29

Reading the Data from an Array Index in the main.ts File in the src Folder

You can modify the data held in any position in a JavaScript array simply by assigning a new value to the index. Just as with regular variables, you can switch the data type at an index without any problems. The output from the listing is as follows:
Index 0: 100
Listing 5-30 demonstrates modifying the contents of an array.
let myArray = [100, "Adam", true];
myArray[0] = "Tuesday";
console.log("Index 0: " + myArray[0]);
Listing 5-30

Modifying the Contents of an Array in the main.ts File in the src Folder

In this example, I have assigned a string to position 0 in the array, a position that was previously held by a number and produces this output:
Index 0: Tuesday

Enumerating the Contents of an Array

You enumerate the content of an array using a for loop or using the forEach method, which receives a function that is called to process each element in the array. Both approaches are shown in Listing 5-31.
let myArray = [100, "Adam", true];
for (let i = 0; i < myArray.length; i++) {
    console.log("Index " + i + ": " + myArray[i]);
}
console.log("---");
myArray.forEach((value, index) => console.log("Index " + index + ": " + value));
Listing 5-31

Enumerating the Contents of an Array in the main.ts File in the src Folder

The JavaScript for loop works just the same way as loops in many other languages. You determine how many elements there are in the array by using the length property.

The function passed to the forEach method is given two arguments: the value of the current item to be processed and the position of that item in the array. In this listing, I have used an arrow function as the argument to the forEach method, which is the kind of use for which they excel (and you will see used throughout this book). The output from the listing is as follows:
Index 0: 100
Index 1: Adam
Index 2: true
Index 0: 100
Index 1: Adam
Index 2: true

Using the Spread Operator

The spread operator is used to expand an array so that its contents can be used as function arguments or combined with other arrays. In Listing 5-32, I used the spread operator to expand an array so that its items can be combined into another array.
let myArray = [100, "Adam", true];
let otherArray = [...myArray, 200, "Bob", false];
for (let i = 0; i < otherArray.length; i++) {
  console.log(`Array item ${i}: ${otherArray[i]}`);
}
Listing 5-32

Using the Spread Operator in the main.ts File in the src Folder

The spread operator is an ellipsis (a sequence of three periods), and it causes the array to be unpacked.
...
let otherArray = [...myArray, 200, "Bob", false];
...
Using the spread operator, I am able to specify myArray as an item when I define otherArray, with the result that the contents of the first array will be unpacked and added as items to the second array. This example produces the following results:
Array item 0: 100
Array item 1: Adam
Array item 2: true
Array item 3: 200
Array item 4: Bob
Array item 5: false

Using the Built-in Array Methods

The JavaScript Array object defines a number of methods that you can use to work with arrays, the most useful of which are described in Table 5-6.
Table 5-6

Useful Array Methods

Method

Description

concat(otherArray)

This method returns a new array that concatenates the array on which it has been called with the array specified as the argument. Multiple arrays can be specified.

join(separator)

This method joins all the elements in the array to form a string. The argument specifies the character used to delimit the items.

pop()

This method removes and returns the last item in the array.

shift()

This method removes and returns the first element in the array.

push(item)

This method appends the specified item to the end of the array.

unshift(item)

This method inserts a new item at the start of the array.

reverse()

This method returns a new array that contains the items in reverse order.

slice(start,end)

This method returns a section of the array.

sort()

This method sorts the array. An optional comparison function can be used to perform custom comparisons.

splice(index, count)

This method removes count items from the array, starting at the specified index. The removed items are returned as the result of the method.

unshift(item)

This method inserts a new item at the start of the array.

every(test)

This method calls the test function for each item in the array and returns true if the function returns true for all of them and false otherwise.

some(test)

This method returns true if calling the test function for each item in the array returns true at least once.

filter(test)

This method returns a new array containing the items for which the test function returns true.

find(test)

This method returns the first item in the array for which the test function returns true.

findIndex(test)

This method returns the index of the first item in the array for which the test function returns true.

foreach(callback)

This method invokes the callback function for each item in the array, as described in the previous section.

includes(value)

This method returns true if the array contains the specified value.

map(callback)

This method returns a new array containing the result of invoking the callback function for every item in the array.

reduce(callback)

This method returns the accumulated value produced by invoking the callback function for every item in the array.

Since many of the methods in Table 5-6 return a new array, these methods can be chained together to process a filtered data array, as shown in Listing 5-33.
let products = [
    { name: "Hat", price: 24.5, stock: 10 },
    { name: "Kayak", price: 289.99, stock: 1 },
    { name: "Soccer Ball", price: 10, stock: 0 },
    { name: "Running Shoes", price: 116.50, stock: 20 }
];
let totalValue = products
    .filter(item => item.stock > 0)
    .reduce((prev, item) => prev + (item.price * item.stock), 0);
console.log("Total value: $" + totalValue.toFixed(2));
Listing 5-33

Processing a Data Array in the main.ts File in the src Folder

I use the filter method to select the items in the array whose stock value is greater than zero and use the reduce method to determine the total value of those items, producing the following output:
Total value: $2864.99

Summary

In this chapter, I provided a brief primer on the JavaScript, focusing on the core functionality that will get you started with the language. Some of the features that I described in this chapter are recent additions to the JavaScript specification and require the TypeScript compiler to convert them to code that can run in older browsers. I continue this theme in the next chapter and introduce some of the more advanced JavaScript features that are used in Angular development.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.134.87.95