Variables, Types, and Collections
Variables
Keyword | Scope | Mutable Assignment |
---|---|---|
var | function | yes |
let | block | yes |
const | block | no |
New variables in JavaScript are declared using one of three keywords: let, const, or var.
JavaScript is case sensitive
var is the most common declarative keyword. It does not have the restrictions that the other two keywords have. This is because it was traditionally the only way to declare a variable in JavaScript. A variable declared with the var keyword is available from the function it is declared in.
An example of scope with a variable declared with var
:
// myVarVariable *is* visible out here for (var myVarVariable = 0; myVarVariable < 5; myVarVariable++) { // myVarVariable is visible to the whole function } // myVarVariable *is* visible out here
let
allows you to declare block-level variables. The declared variable is available from the block it is enclosed in.
// myLetVariable is *not* visible out here for (let myLetVariable = 0; myLetVariable < 5; myLetVariable++) { // myLetVariable is only visible in here } // myLetVariable is *not* visible out here
Constants
All variables are pointers. Assignment is the act of pointing that variable to something in memory. Mutability is whether or not a variable can be reassigned once it has initially been assigned something. Using var
or let
creates mutable pointers, whereas const
is immutable.
var myBike = "Mountain Bike"; let currentGear = 5; const numberOfGears = 12; //reassignment myBike = "Penny Farthing"; // this works currentGear = 1; // so does this numberOfGears = 1; // error
When working with objects (rather than primitives), remember that const
only prevents reassigning your variable to a different object. The object itself (its properties, functions, and so on) can still be changed
// call constructor, new object, assign it to bike const bike = new Bike(); //Change internal state by calling a function bike.changeGear("front", "Up"); // add a new member to bike that did not exist before bike.type = "Penny Farthing"; // check for success console.log(bike.calculateGearRatio()); // 4.0909... console.log(bike.type); // "Penny Farthing" // attempt to point bike to new instance of Bike bike = new Bike(1,2); // error
const
allows you to declare variables whose values are never intended to change. The variable is available from the block it is declared in.
const Pi = 3.14; // variable Pi is set Pi = 1; // will throw an error because you cannot change a constant variable.
If you declare a variable without assigning any value to it, its type is undefined
.
An important difference between JavaScript and other languages like Java is that in JavaScript, blocks do not have scope; only functions have a scope.
Types
Numbers
Numbers in JavaScript are “double-precision 64-bit format IEEE 754 values”, according to the spec. This has some interesting consequences.
0.1 + 0.2 == 0.30000000000000004;
The standard arithmetic operators are supported, including addition, subtraction, modulus (or remainder) arithmetic, and so forth. There’s also a built-in object called Math.
Math.sin(3.5); var circumference = 2 * Math.PI * r;
You can convert a string to an integer using the built-in parseInt()
function. This takes the base for the conversion as an optional second argument, which you should always provide
parseInt('123', 10); // 123 parseInt('010', 10); // 10
If you want to convert a binary number to an integer, just change the base:
parseInt('11', 2); // 3
Similarly, you can parse floating point numbers using the built-in parseFloat()
function. Unlike its parseInt()
, parseFloat()
always uses base 10.
You can also use the unary +
operator to convert values to numbers:
+ '42'; // 42 + '010'; // 10 + '0x10'; // 16
A special value called NaN
(short for “Not a Number”) is returned if the string is non-numeric:
parseInt('hello', 10); // NaN
NaN
is toxic: if you provide it as an operand to any mathematical operation, the result will also be NaN
:
NaN + 5; // NaN
You can test for NaN
using the built-in isNaN()
function:
isNaN(NaN); // true
JavaScript also has the special values Infinity
and -Infinity
:
1 / 0; // Infinity -1 / 0; // -Infinity
You can test for Infinity
, -Infinity
and NaN
values using the built-in isFinite()
function:
isFinite(1 / 0); // false isFinite(-Infinity); // false isFinite(NaN); // false
The parseInt()
and parseFloat()
functions parse a string until they reach a character that isn’t valid for the specified number format, then return the number parsed up to that point. However the “+” operator simply converts the string to NaN
if there is an invalid character contained within it.
Strings
Strings in JavaScript are sequences of Unicode characters (UTF-16). To find the length of a String (in code units), access its length
property:
'hello'.length; // 5
You can use strings like objects. They have methods as well that allow you to manipulate the string and access information about the string
'hello'.charAt(0); // "h" 'hello, world'.replace('world', 'mars'); // "hello, mars" 'hello'.toUpperCase(); // "HELLO"
Dates
JavaScript comes with the built in Date
object and related methods
The Date
object is a built-in object in JavaScript that stores the date and time. It provides a number of built-in methods for formatting and managing that data.
By default, a new Date
instance without arguments provided creates an object corresponding to the current date and time. This will be created according to the current computer’s system settings. JavaScript, however, understands the date based on a timestamp called epoch time and we can get it with getTime()
// Set variable to current date and time const now = new Date(); // View the output console.log("" + now); // "Mon Mar 02 2020 09:57:22 GMT+0100 (hora estándar de Europa central)" console.log(now.getTime()); //1583139516795
Different ways to create Dates
Date Creation | Output |
---|---|
new Date() | Current date and time |
new Date(timestamp) | Creates date based on milliseconds since Epoch time |
new Date(date string) | Creates date based on date string |
new Date(year, month, day, hours, minutes, seconds, milliseconds) | Creates date based on specified date and time |
We can modify Date properties after the creation with set methods
Date/Time | Method | Range | Example |
---|---|---|---|
Year | setFullYear() | YYYY | 1970 |
Month | setMonth() | 0-11 | 0 = January |
Day (of the month) | setDate() | 1-31 | 1 = 1st of the month |
Day (of the week) | setDay() | 0-6 | 0 = Sunday |
Hour | setHours() | 0-23 | 0 = midnight |
Minute | setMinutes() | 0-59 | |
Second | setSeconds() | 0-59 | |
Millisecond | setMilliseconds() | 0-999 | |
Timestamp | setTime() | Milliseconds since Epoch time |
And we have several methods to get the Date information
Date/Time | Method | Range | Example |
---|---|---|---|
Year | getFullYear() | YYYY | 1970 |
Month | getMonth() | 0-11 | 0 = January |
Day (of the month) | getDate() | 1-31 | 1 = 1st of the month |
Day (of the week) | getDay() | 0-6 | 0 = Sunday |
Hour | getHours() | 0-23 | 0 = midnight |
Minute | getMinutes() | 0-59 | |
Second | getSeconds() | 0-59 | |
Millisecond | getMilliseconds() | 0-999 | |
Timestamp | getTime() | Milliseconds since Epoch time |
However, these get
methods retrieve the date components based on the user’s local timezone settings. For increased control we can use the getUTC
methods that calculate the time based on the UTC standard
Date/Time | Method | Range | Example |
---|---|---|---|
Year | getUTCFullYear() | YYYY | 1970 |
Month | getUTCMonth() | 0-11 | 0 = January |
Day (of the month) | getUTCDate() | 1-31 | 1 = 1st of the month |
Day (of the week) | getUTCDay() | 0-6 | 0 = Sunday |
Hour | getUTCHours() | 0-23 | 0 = midnight |
Minute | getUTCMinutes() | 0-59 | |
Second | getUTCSeconds() | 0-59 | |
Millisecond | getUTCMilliseconds() | 0-999 |
Other types
JavaScript distinguishes between null
, which is a value that indicates a deliberate non-value (and is only accessible through the null
keyword), and undefined
, which is a value of type undefined
that indicates an uninitialized variable — that is, a value hasn’t even been assigned yet.
JavaScript has a boolean type, with possible values true
and false
(both of which are keywords.)
Truthy and Falsy
When an expression expects a Boolean value, the following values are always treated as false.
false
(of course)0
(the number zero)""
or''
(an empty string)null
undefined
NaN
(the result of failed mathematical operations)
false
is false
(of course!). The rest of these values are coerced to false
. As a group they are referred to as falsy.
There’s no question that true
is just that—true
. But any other value of any type is coerced to true
. We call these values truthy.
This is widely accepted
const myRecord = response.getReturnValue(); if (myRecord) { //now process the record }
Boolean operations such as &&
(logical and), ||
(logical or), and !
(logical not) are supported;
Coercion
When most JavaScript operators encounter an invalid type, they attempt to convert the value to a valid type. This process of implicitly converting a type is called implicit type coercion.
let num1 = 9 * "3"; console.log(num1); // 27 (a number) let num2 = 9 + "3"; console.log(num2); // "93" (a string)
Don’t Use Implicit Type Coercion
false == ""; // true false == "0"; // true "" == "0"; // false [0] == 0; // true
For Boolean comparison the best practice is to use ===
and !==
. With these operators, primitive types are only equivalent when both type and value match, and object comparisons are only true when their respective pointers are pointing to the same memory address. Trying the same comparisons as above:
false === ""; // false false === "0"; // false "" === "0"; // false [0] === 0; // false
Arrays
Arrays are list-like objects whose prototype has methods to perform traversal and mutation operations. Neither the length of a JavaScript array nor the types of its elements are fixed. Since an array’s length can change at any time, and data can be stored at non-contiguous locations in the array, JavaScript arrays are not guaranteed to be dense;
Arrays cannot use strings as element indexes (as in an associative array) but must use integers.
Setting or accessing via non-integers using bracket notation (or dot notation) will not set or retrieve an element from the array list itself, but will set or access a variable associated with that array’s object property collection.
Create Array
let fruits = ['Apple', 'Banana'] console.log(fruits.length); // 2
Access (index into) an Array item
let first = fruits[0]; // Apple let last = fruits[fruits.length - 1]; // Banana
Iterate
fruits.forEach(function(item, index, array) { console.log(item, index); }) // Apple 0 // Banana 1
Add to the end of an Array
let newLength = fruits.push('Orange'); // ["Apple", "Banana", "Orange"]
Remove from the end of an Array
let last = fruits.pop(); // remove Orange (from the end) // ["Apple", "Banana"]
Remove from the front of an Array
let first = fruits.shift(); // remove Apple from the front // ["Banana"]
Add to the front of an Array
let newLength = fruits.unshift('Strawberry'); // add to the front // ["Strawberry", "Banana"]
Find the index of an item in the Array
fruits.push('Mango'); // ["Strawberry", "Banana", "Mango"] let pos = fruits.indexOf('Banana'); // 1
Remove an item by index position
let removedItem = fruits.splice(pos, 1); // this is how to remove an item // ["Strawberry", "Mango"]
Copy an Array
let vegetables = ['Cabbage', 'Turnip', 'Radish', 'Carrot']; console.log(vegetables); // ["Cabbage", "Turnip", "Radish", "Carrot"] let shallowCopy = vegetables.slice(); console.log(shallowCopy); // ["Cabbage", "Turnip", "Radish", "Carrot"]
Accessing array elements
JavaScript arrays are zero-indexed: the first element of an array is at index 0, and the last element is at the index equal to the value of the array’s length property minus 1.
There is nothing special about JavaScript arrays and the properties that cause this. JavaScript properties that begin with a digit cannot be referenced with dot notation, and must be accessed using bracket notation.
let years = [1950, 1960, 1970, 1980, 1990, 2000, 2010]; console.log(years.0); // a syntax error console.log(years[0]); // works properly renderer.3d.setTexture(model, 'character.png'); // a syntax error renderer['3d'].setTexture(model, 'character.png'); // works properly
When setting a property on a JavaScript array when the property is a valid array index and that index is outside the current bounds of the array, the engine will update the array’s length
property accordingly:
fruits[5] = 'mango' console.log(fruits[5]) // 'mango' console.log(Object.keys(fruits)) // ['0', '1', '2', '5'] console.log(fruits.length) // 6
JSON
JSON is a text-based data format following JavaScript object syntax. Even though it closely resembles JavaScript object literal syntax, it can be used independently from JavaScript.
JSON exists as a string — useful when you want to transmit data across a network. It needs to be converted to a native JavaScript object when you want to access the data. This is not a big issue — JavaScript provides a global JSON object that has methods available for converting between the two.
Accesing data
let myJSON = { "name": "Chris", "age": "38" }; console.log(myJSON['age']); // 38 console.log(myJSON['name']); // Chris
If we have to deal with a complex JSON object we can traverse the properties like this
staffJSON['members'][1]['roles'][2];
Convert String to JSON
request.open('GET', requestURL); request.responseType = 'text'; // now we're getting a string! request.send(); request.onload = function() { const superHeroesText = request.response; // get the string from the response const superHeroes = JSON.parse(superHeroesText); // convert it to an object populateHeader(superHeroes); showHeroes(superHeroes); }
Convert JSON to String
let myJSON = { "name": "Chris", "age": "38" }; console.log(typeof myJSON); // object let myString = JSON.stringify(myJSON); console.log(typeof myString); // string