Key-value collections with a prototype chain, property descriptors, and more control than they look like they have.
At their core, JavaScript objects are just collections of key-value pairs, but almost everything in the language — arrays, functions, even class instances — is built on top of this same object model. Every object also has an internal link to a prototype object, and property lookups that don't find a match on the object itself walk up that prototype chain until they find one or hit null — which is how inherited methods work without every object needing its own copy.
Beyond the basic key-value view, every property actually has a descriptor controlling whether it's writable, enumerable, and configurable, which is what Object.freeze, Object.seal, and getters/setters are built on. Understanding property descriptors explains behavior that otherwise looks like magic — why a 'frozen' object's nested objects are still mutable, or why a for...in loop skips some properties that Object.keys shows.
What you'll walk away knowing