Basics
Variables and constants
Constants and variables in JavaScript are loosely typed. Expressions (phrases) are evaluated to produce a value, while statements (sentences) are executed to make something happen. Each statement ends with a semicolon. A variable can be created without let
or const
keywords. In such case, a global variable is created that can be a source of bugs. Use the directive to initiate strict mode to prevent this behavior.
"use strict";
// Constants
const myName = "Roman Akchurin";
// Variables
let myCity = "Moscow";
// Print to console
console.log(myCity);
Numbers
Integers can be expressed in base-10 as well as hexadecimal, octal, or binary representation. Floating-point literals are represented in decimal point format or using exponential notation. Underscores can be used to break long literals for readability.
// Numbers
const decimal = 3.14;
const aDecimal = 0.123_456_789;
const anotherDecimal = 6.02e23;
const yetAnotherDecimal = 1.4738223e-32;
const integer = 1_000_000;
const hexadecimal = 0x89_ab_cd_ef;
const binary = 0b0001_1101_0111;
const octal = 0o277;
BigInt can represent an arbitrarily large integer.
const bigInteger = 1_000_000_000_000_000n;
const bigBinary = 0b0111_1111n;
const bigOctal = 0o7777n;
const bigHexadecimal = 0xab_cd_efn;
// Converting regular numbers or strings to BigInt
const manyZeros = "1" + "0".repeat(100);
const reallyBigNumber = BigInt(manyZeros);
You can perform basic arithmetic with BigInt, however they cannot be mixed with regular numbers.
// Arithmetic with BigInt
1000n + 2000n;
3000n - 2000n;
2000n * 3000n;
3000n / 997n; // => 3n: Division drops the remainder and rounds down
3000n % 997n; // => 9n
2n ** 131071n - 1n; // A Mersenne prime with 39457 decimal digits
As in most other modern programming languages, floating-point representations are not exact in JavaScript.
let pointOne = 0.3 - 0.2;
let anotherPointOne = 0.2 - 0.1;
pointOne === anotherPointOne; // False
pointOne === 0.1; // False
anotherPointOne === 0.1; // True
Math functions
JavaScript has a wide range of built-in math functions.
// Math functions and constants
Math.pow(2, 53);
Math.round(0.6);
Math.ceil(0.6);
Math.floor(0.6);
Math.abs(-5);
Math.max(1, 2, 3);
Math.min(4, 5, 6);
Math.random();
Math.PI;
Math.E;
Math.sqrt(3);
Math.pow(3, 1 / 3);
Math.sin(0);
Math.log(10);
Math.log(100) / Math.LN10;
Math.log(512) / Math.LN2;
Math.exp(3);
Math.cbrt(27); // Cube root
Math.hypot(3, 4); // Square root of sum of squares of all arguments
Math.log10(100);
Math.log2(1024);
Math.log1p(0.01); // Natural log of (1+x)
Math.expm1(0.01); // Math.exp(x) - 1; the inverse of Math.log1p()
Math.sign(-1); // -1, 0, or 1 for <, ==, or > 0
Math.imul(2, 3); // Optimized multiplication of 32-bit integer
Math.clz32(0xf); // Number of leading zero bits in a 32-bit integer
Math.trunc(3.9); // Convert to integer by truncating fractional part
Math.fround(3.4); // Round to nearest 32-bit float number
Math.sinh(1); // Hyperbolic sine. Also Math.cosh(), Math.tanh()
Math.asinh(2); // Hyperbolic arcsine. Also Math.acosh(), Math.atanh()
// Number methods and properties
Number.parseInt("3.14");
Number.parseFloat(".99");
Number.isNaN(NaN);
Number.isFinite(Infinity);
Number.isInteger(3.13);
Number.isSafeInteger(2 ** 53); // Is integer in range -2**53...2**53
Number.MIN_SAFE_INTEGER; // => -(2**53 - 1)
Number.MAX_SAFE_INTEGER; // => 2**53 - 1
Number.EPSILON; // => 2**-52: smallest difference between numbers
Number.NEGATIVE_INFINITY;
Number.POSITIVE_INFINITY;
Number.NaN;
Number.MIN_VALUE;
Number.MAX_VALUE;
Strings
Strings are denoted by a matching pair of single quotes, double quotes, or backticks. String interpolation is possible with backtick notation. Generic escape sequences can represent any character in a string by providing its Unicode character code.
'two\nlines';
"one\
long\
line";
const line_count = 2;
`the newline character at the end of this line
is included in this ${line_count}-line string`;
"\xa9"; // Unicode character © encoded by two hexadecimal digits nn
"\u263A"; // Unicode character ☺ encoded by four hexadecimal digits nnnn
"\u{1F60A}"; // Unicode character 😊 encoded by codepoint n,
// where n is one to six hexadecimal digits between 0 and 10FFFF
String operations
There is a wide range of methods that perform operations on strings in JavaScript. Strings are immutable in JavaScript, therefore string methods always return new strings.
let s = "Hello, " + "world";
s.length; // => 12
// Obtaining portions of string
s.substring(1, 4); // => "ell"
s.slice(1, 4); // => "ell"
s.slice(-3); // => "rld"
s.split(", "); // => ["Hello", "world"]
// Searching a string
s.indexOf("l"); // => 2: position of the first letter l
s.indexOf("l", 3); // => 3: position of fist "l" at or after 3
s.indexOf("zz"); // => -1: s does not include the substring "zz"
s.lastIndexOf("l"); // => 10: position of last letter l
// Boolean searching functions
s.startsWith("Hell"); // => true: the string starts with these
s.endsWith("!"); // => false: s does not end with that
s.includes("or"); // => true: s includes substring "or"
// Creating modified versions of a string
s.replace("llo", "ya"); // => "Heya, world"
s.toLowerCase(); // => "hello, world"
s.toUpperCase(); // => "HELLO, WORLD"
s.normalize(); // Unicode NFC normalization
s.normalize("NFD"); // NFD normalization. Also "NFCK", "NFKD"
// Inspecting individual 16-bit characters of a string
s.charAt(0); // => "H": the first character
s.charAt(s.length - 1); // => "d": the last character
s.charCodeAt(0); // => 72: 16-bit number at the specified position
s.codePointAt(0); // => 72: work for codepoints > 16 bits
// String padding
"x".padStart(3); // => " x": add spaces on the left to a length of 3
"x".padEnd(3); // => "x ": add spaces on the right to a length of 3
"x".padStart(3, "*"); // => "**x": add starts on the left to a length of 3
"x".padEnd(3, "-"); // => "x--": add dashes on the right to a length of 3
// String trimming
" test ".trim(); // => "test": remove spaces at start and end
" test ".trimStart(); // => "test ": remove spaces on left. Also trimLeft()
" test ".trimEnd(); // => " test": remove spaces at right. Also trimRight()
// Other string methods
s.concat("!"); // => "Hello world!"
"<>".repeat(5); // => "<><><><><>": concatenate n copies
s[0]; // => "H"
s[s.length - 1]; // => "d"
You don't need parenthesis to invoke a function on template literals.
`\n`.length; // => 1: the string has a single newline character
String.raw`\n`.length; // => 2: a backslash character and the letter n
Regular expressions
Text between a pair of forward slashes makes a regular expression. Letters after the second slash modify the expression.
/^HTML/; // Match the letters H T M L at the start of a string
/[1-9][0-9]*/; // Match a nonzero digit, followed by any # of digits
/\bjavascript\b/i; // Match "javascript" as a word, case-insensitive
const text = "testing: 1, 2, 3"; // Sample text
const pattern = /\d+/g; // Matches all instances of one or more digits
pattern.test(text); // => true: a match exists
text.search(pattern); // => 9: position of first match
text.match(pattern); // ["1", "2", "3"]: array of all matches
text.replace(pattern, "#"); // => "testing: #, #, #"
text.split(/\D+/); // => ["", "1", "2", "3"]: split on nondigits
Boolean values
Boolean values true
and false
are generally the result of comparison operators in JavaScript. However, values in control structures like if/else
statement are converted to boolean values as well. Only the following values are converted to false.
false;
undefined; // System-level, unexpected, or error-like absence of value
null; // Program-level, normal, or expected absence of value
0;
-0;
NaN;
"";
Global object
Global object in JavaScript defines all global identifiers (constants, functions, constructors, and other global objects) that become available when the program starts. In node, the global object has a property global
that refers to the global object itself. In web browsers, the same is done with window
property. In general, globalThis
refers to the global object in any environment.
Primitive types vs. reference types
Number, boolean, string, null
and undefined
are immutable primitive types. They are equal if they hold the same value. In contrast, object (array is object) is a mutable reference type. Two objects are equal if they refer to the same object.
Type conversions
JavaScript is flexible in converting types to what is expected. However, explicit type conversion can help avoid bugs.
Number("3"); // => 3
+"3"; // => 3
"3" - 0; // => 3
String(false); // => "false"
false + ""; // => "false"
Boolean([]); // => true
!![]; // => true
Number to string conversion can be done with toString()
method or more specialized toFixed()
, toExponential()
, or toPrecision()
methods.
const myNumber = 17;
const myBinary = "0b" + myNumber.toString(2); // => "0b10001"
const myOctal = "0o" + myNumber.toString(8); // => "0o21"
const myHexadecimal = "0x" + myNumber.toString(16); // => "0x11"
const anotherNumber = 123456.789;
anotherNumber.toFixed(0); // => "123457"
anotherNumber.toFixed(2); // => "123456.79"
anotherNumber.toFixed(5); // => "123456.78900"
anotherNumber.toExponential(1); // => "1.2e+5"
anotherNumber.toExponential(3); // => "1.235e+5"
anotherNumber.toPrecision(4); // => "1.235e+5"
anotherNumber.toPrecision(7); // => "123456.8"
anotherNumber.toPrecision(10); // => "123456.7890"
String to number conversion can be performed with parseInt()
or parseFloat()
functions.
parseInt("3 blind mice"); // 3
parseFloat(" 3.14 meters"); // 3.14
parseInt("-12.34"); // -12
parseInt("0xFF"); // 255
parseInt("0xff"); // 255
parseInt("-0xFF"); // -255
parseFloat(".1"); // 0.1
parseInt("0.1"); // 0
parseInt(".1"); // NaN
parseFloat("$72.47"); // NaN
// Optional argument to specify the base
parseInt("11", 2); // 3: (1*2 + 1)
parseInt("ff", 16); // 255: (15*16 + 15)
parseInt("zz", 36); // 1295: (35*36 + 35)
parseInt("077", 8); // 63: (7*8 + 7)
parseInt("077", 10); // 77: (7*10 + 7)
Destructuring
Destructuring is a form of compound declaration in JavaScript. It allows you to initialize variables and constants from objects more easily.
let [x, y] = [1, 2]; // Same as let x=1, y=2
[x, y] = [y, x]; // Swap the values of the two variables
// Copy Math object functions into variables
const { sin, cos, tan } = Math;
// Destructuring array of objects
let points = [
{ x: 1, y: 2 },
{ x: 3, y: 4 },
];
let [{ x: x1, y: y1 }, { x: x2, y: y2 }] = points;
Arrays
Arrays are initialized with square brackets. Undefined elements can be included in an array by omitting a value between commas. A single trailing comma is allowed and does not create an undefined element.
[]; // Empty array
[1,2]; // 2-element array
[1,,,,5]; // Sparse array
Objects
Object initializer is similar to that of arrays, but with curly braces instead. Object properties are access by dot-notation or by using square brackets. Optional chaining allows accessing optional properties without throwing a type error if the property is null
or undefined
. Optional chaining implements short-circuiting by skipping further evaluation when an invalid property has been accessed.
{}; // Empty object
const q = { x: 1.2, y: -0.5 }; // Object with 2 properties
const rectangle = {
upperLeft: { x: 2, y: 2 },
lowerRight: { x: 4, y: 5 }
} // Object with nested objects
rectangle.upperLeft.x; // => 2
q["y"]; // => -0.5
q.z?.r; // => undefined
rectangle.upperRight?.["x"]; // => undefined
Functions
Function definition consists of the keyword function
with parameters names in parentheses and a block of code in curly braces. Conditional function invocation allows to skip function invocation with short-circuiting) if the identifier evaluates to null
or undefined
.
let square = function(x) { return x * x; };
function anotherSquare(x) { return x**2; };
let yetAnotherSquare = x => x * x; // Arrow function
let foo;
foo?.(); // Conditional invocation
q.foo?.(); // Conditional invocation with property access