Compile Ready
Module 6 · Objects & Prototypes

Object.create

Intermediate9m read6m practice15m total
Object.createNull PrototypeDelegationDescriptors

Introduction

Object.create(proto) creates a new object whose internal [[Prototype]] is exactly proto. It is the most direct way to build prototype delegation without invoking a constructor function or using class.

Its second argument also lets you define properties with descriptors at creation time, which connects this API directly to property descriptors.

Why This Matters

Object.create is the cleanest way to explain prototype delegation. It also solves a real security and correctness problem: null-prototype dictionaries avoid accidental collisions with inherited names such as toString, constructor, or __proto__.

Theory

Basic form

Object.create(proto) returns a fresh empty object whose prototype is proto. Reads that miss on the new object continue on proto. Writes usually create or update own properties on the receiver, not on the prototype.

Second argument: descriptors

Object.create(proto, descriptors) works like creating the object and then calling Object.defineProperties. Descriptor defaults are the same strict defaults: omitted writable, enumerable, and configurable flags are false.

Null-prototype objects

Object.create(null) creates an object with no prototype at all. It does not inherit toString, valueOf, constructor, or hasOwnProperty. This is useful for dictionary-style data where every key should be user data, not inherited behaviour.

Trade-offs of null-prototype dictionaries

The benefit is no inherited-key collision. The cost is that common object methods are missing, so you must use safe static or borrowed APIs such as Object.keys(dict) and Object.prototype.hasOwnProperty.call(dict, key).

Relationship to inheritance

Constructor-function inheritance commonly uses Child.prototype = Object.create(Parent.prototype). That gives instances of Child a prototype chain that reaches Parent.prototype without running the parent constructor just to set up inheritance.

Visual Diagrams

Object.create sets the next lookup step
const child = Object.create(parent)

child
+---------------------+
| own name: 'Ada'     |
+---------------------+
          |
          v
parent
+---------------------+
| role: 'reader'      |
+---------------------+
          |
          v
Object.prototype
+---------------------+
| toString, valueOf   |
+---------------------+

The created object starts empty but delegates missing reads to the prototype you pass in.

Null-prototype dictionary
dictionary = Object.create(null)

+---------------------+
| apple: 2            |
| toString: 1         |  own data key, not inherited method
+---------------------+
          |
          v
        null

With no prototype, every key is data you explicitly put there.

Code Examples

Create an object that delegates to defaults

The order has its own total but inherits currency from defaults.

Loading…

Use a null-prototype dictionary

A null-prototype object is useful when user-provided keys should not collide with inherited object methods.

Loading…

Playground

Loading editor…
Console

Press Run to execute the code and see output here.

Output Prediction

Predict the output #1

javascript
1const base = { role: 'reader' };
2const user = Object.create(base);
3
4user.name = 'Ada';
5
6console.log(user.role);
7console.log(Object.keys(user).join(','));
8console.log(Object.getPrototypeOf(user) === base);

Predict the output #2

javascript
1const obj = Object.create(null, {
2 id: { value: 1, enumerable: true },
3 hidden: { value: 2 }
4});
5
6console.log(Object.keys(obj).join(','));
7console.log(obj.hidden);
8console.log(Object.getPrototypeOf(obj));

Coding Exercises

Build a safe string counter

Medium

Implement countWords(words) so it returns a null-prototype dictionary mapping each word to its count. Keys like toString and constructor must be counted as normal words.

Interview Questions

1What does `Object.create(proto)` do?

It creates a new object whose internal [[Prototype]] is proto. The new object starts with no own properties unless descriptors are provided. Missing property reads delegate to proto through the prototype chain.

Asked at:GoogleMicrosoft

Follow-ups

  • What happens if `proto` is `null`?
  • How does the second argument work?
2Why would you use `Object.create(null)`?

It creates a dictionary object with no inherited keys. That prevents collisions with names like toString, constructor, or hasOwnProperty. The trade-off is that those inherited methods are unavailable, so you should use static or borrowed object utilities.

Asked at:AmazonMeta

Quiz

1. What is the prototype of `Object.create(null)`?

2. What does the second argument to `Object.create` contain?

Summary

  • `Object.create(proto)` creates an object with an explicit prototype.
  • The second argument defines own properties through descriptors.
  • `Object.create(null)` is useful for dictionary objects with no inherited-key collisions.
  • Constructor-function inheritance commonly uses `Object.create(Parent.prototype)`.

Cheat Sheet

Basic: const child = Object.create(parent)

Null dictionary: const dict = Object.create(null)

With descriptors: Object.create(proto, { id: { value: 1, enumerable: true } })

Own keys: inherited properties do not appear in Object.keys(child).

Caution: null-prototype objects do not have hasOwnProperty as a method.