Creating, reading, and transforming plain JavaScript objects.

Basics

Introduction

Objects are collections of key-value pairs; keys are strings or symbols.

Literals

const defaults = { color: 'red', size: 'md' }
const name = 'Ada'

const user = {
  name,                      // same as name: 'Ada'
  ['role' + 'Id']: 7,        // computed key: roleId
  greet() { return 'hi' },   // method shorthand
}
const opts = { ...defaults, visible: true }
// → { color: 'red', size: 'md', visible: true }

Shorthand uses the variable name as the key; spread copies own enumerable properties.

See: Object initializer, Spread syntax (developer.mozilla.org)

Accessing

user.name                // → 'Ada'  (dot)
user['name']             // → 'Ada'  (bracket)
user[key]                // dynamic key from a variable
user.address?.city       // → undefined (no address)
user.nickname ?? 'anon'  // → 'anon' (nullish fallback)
const { a, b = 1, ...rest } = obj
const { name: who = 'anon' } = user

Bracket access takes any expression; ?. short-circuits on null or undefined.

See: Property accessors, Optional chaining, Nullish coalescing (developer.mozilla.org)

Checking keys

'name' in user                   // → true (own or inherited)
Object.hasOwn(user, 'name')      // → true (own only, ES2022)
Object.hasOwn(user, 'toString')  // → false

in walks the prototype chain; Object.hasOwn() checks own properties only. Older code uses Object.prototype.hasOwnProperty.call().

See: in operator, Object.hasOwn() (developer.mozilla.org)

Setting and deleting

user.age = 36            // set with dot
user[key] = value        // computed key
user.age += 1            // update in place
delete user.age          // → true
'age' in user            // → false

Assigning a computed key adds or overwrites a property; delete removes one.

See: delete operator (developer.mozilla.org)

Operations

Static methods

CallReturns
Object.keys(obj)own enumerable keys
Object.values(obj)own enumerable values
Object.entries(obj)[key, value] pairs
Object.fromEntries(e)object from pairs
Object.assign(t, s)target with sources merged
Object.freeze(obj)obj, then immutable
Object.seal(obj)obj, no add or remove
Object.create(proto)object with given proto

fromEntries() reverses entries(); freeze() and seal() are shallow.

See: Object.keys(), Object.fromEntries(), Object.freeze() (developer.mozilla.org)

Iterating

for (const [key, value] of Object.entries(user)) {
  console.log(key, value)
}

Object.entries(user).forEach(([key, value]) => {
  console.log(key, value)
})

Object.entries() with for...of visits own enumerable keys only. Prefer it over for...in, which also walks inherited keys.

See: Object.entries(), for...of (developer.mozilla.org)

Copying

const shallow = { ...user }                       // own props
const merged = Object.assign({}, user, extra)
const deep = structuredClone(user)                // nested objects
const viaJson = JSON.parse(JSON.stringify(user))  // loses dates

Spread and Object.assign() are shallow; structuredClone() (Node 17+) copies nested objects. JSON round-trips lose dates, functions, and undefined.

See: Spread syntax, Object.assign(), structuredClone() (developer.mozilla.org)

Comparing

const a = { x: 1 }
const b = { x: 1 }
a === b               // → false, different references
Object.is(NaN, NaN)   // → true
Object.is(0, -0)      // → false

=== compares object identity, not contents; Object.is() treats NaN as equal to itself.

See: Strict equality, Object.is() (developer.mozilla.org)

0 Comments for this cheatsheet. Write yours!