JavaScript is dynamically typed: values have types, variables do not. This chapter tours the primitive types, objects, arrays and their methods, Map and Set, classes and prototypes, and JSON.
Primitives
There are seven primitive types. Primitives are immutable and compared by value.
console.log(0.1 + 0.2); // 0.30000000000000004, floating-point rounding
console.log(Number("42px")); // NaN
console.log(Number.isNaN(NaN)); // true
console.log(2 ** 53 + 1); // 9007199254740992, precision runs out
console.log(2n ** 53n + 1n); // 9007199254740993n, bigint stays exact
Every number is a 64-bit float, so do money math in whole units such as cents. The falsy values are false, 0, -0, 0n, "", null, undefined and NaN; everything else, including [] and {}, is truthy.
Objects
An object is a bag of key/value pairs. Use dot or bracket access, and use shorthand when a variable already has the key's name. Objects are passed by reference, so assigning one to another variable does not copy it.
const name = "Jordan";
const user = {
name, // shorthand for name: name
age: 29,
"favorite-color": "blue",
introduce() {
return `I'm ${this.name}.`;
},
};
console.log(user["favorite-color"]); // "blue"
console.log(user.introduce()); // "I'm Jordan."
for (const [key, value] of Object.entries(user)) {
console.log(key, typeof value);
}
const alias = user;
alias.age = 30;
console.log(user.age); // 30, same object
Arrays and array methods
Array methods say what you mean more clearly than hand-written loops. map, filter and reduce return something new and leave the original alone; push, sort, reverse and splice mutate in place.
const products = [
{ name: "mouse", price: 25, stock: 3 },
{ name: "monitor", price: 320, stock: 0 },
{ name: "keyboard", price: 89, stock: 7 },
];
const names = products.map((p) => p.name);
const inStock = products.filter((p) => p.stock > 0);
const total = products.reduce((sum, p) => sum + p.price, 0); // 434
const monitor = products.find((p) => p.name === "monitor");
const anySoldOut = products.some((p) => p.stock === 0); // true
const allCheap = products.every((p) => p.price < 100); // false
// sort mutates, so copy first
const byPrice = [...products].sort((a, b) => a.price - b.price);
Without a compare function, sort() compares elements as strings, so [10, 9, 1].sort() gives [1, 10, 9]. Always pass (a, b) => a - b for numbers.
Map and Set
Map is a key/value store that accepts any value as a key; Set holds unique values. Prefer Map over a plain object when keys are added and removed often or are not strings.
const visits = new Map();
visits.set("/home", 10);
visits.set("/home", visits.get("/home") + 1);
console.log(visits.get("/home"), visits.size); // 11 1
const tags = new Set(["js", "web", "js"]);
console.log(tags.size, tags.has("web")); // 2 true
const unique = [...new Set([3, 1, 3, 2, 1])]; // [3, 1, 2]
Classes and prototypes
Every object inherits from another object, its prototype. The class syntax is a readable layer over this prototype-based inheritance. Fields starting with # are private and invisible outside the class.
class Account {
#balance = 0;
constructor(owner) {
this.owner = owner;
}
deposit(amount) {
if (amount <= 0) throw new RangeError("Amount must be positive");
this.#balance += amount;
return this;
}
get balance() {
return this.#balance;
}
}
class SavingsAccount extends Account {
constructor(owner, rate) {
super(owner);
this.rate = rate;
}
}
const acc = new SavingsAccount("Lee", 0.03).deposit(1000);
console.log(acc.balance); // 1000
console.log(acc instanceof Account); // true
console.log(Object.getPrototypeOf(acc) === SavingsAccount.prototype); // true
Methods live once on the prototype rather than on each instance. When a property is missing on an object, lookup climbs the prototype chain until it finds it or runs out.
JSON
JSON is the lingua franca for exchanging data. JSON.stringify turns a value into text and JSON.parse turns text back into a value.
const data = { id: 1, createdAt: new Date(0), secret: undefined };
const text = JSON.stringify(data, null, 2); // pretty-print with 2 spaces
const parsed = JSON.parse(text);
console.log(typeof parsed.createdAt); // "string": dates do not survive
console.log("secret" in parsed); // false: undefined is dropped
const copy = structuredClone(data); // deep copy that keeps the Date
JSON cannot hold functions, undefined or symbols, and dates become strings. Malformed input makes JSON.parse throw a SyntaxError, so wrap untrusted data in try...catch.
Summary
- Seven primitives are handled by value; objects are handled by reference.
- Learn
map, filter, reduce and find, and remember that sort mutates. - Use
Map for dynamic keys and Set for de-duplication. class wraps prototype inheritance and supports #private fields.- Know what JSON does to dates and
undefined before relying on it.
0 comments
Sign in · Sign in to leave a comment.