JavaScript Prototypal Inheritance Deep Dive Guide

Table of Contents

1. Introduction: The True Nature of JavaScript Objects

JavaScript’s object system stands apart from most mainstream programming languages. While languages like Java, C++, and C# use class-based inheritance, JavaScript employs a more flexible and dynamic approach: prototypal inheritance. This fundamental difference often confuses developers coming from class-based languages and represents one of JavaScript’s most powerful, yet misunderstood, features.

At its core, JavaScript is a prototype-based language where objects can inherit properties and methods directly from other objects. This model, inspired by Self programming language, provides incredible flexibility and dynamic capabilities that class-based systems struggle to match. Every object in JavaScript contains an internal link to another object called its prototype, and this chain of linked objects forms the basis of inheritance.

The introduction of ES6 classes in 2015 created a misconception that JavaScript had adopted class-based inheritance. However, Brendan Eich, JavaScript’s creator, has repeatedly emphasized that “classes in JavaScript are syntactic sugar over the existing prototype-based inheritance” and do not change JavaScript’s fundamental nature. Understanding prototypes is not just academic—it’s essential for writing efficient, maintainable JavaScript code and for debugging complex issues that inevitably arise when working with object relationships.

2. Historical Context: How JavaScript Got Its Prototype System

To fully appreciate JavaScript’s prototypal inheritance, we must understand its historical context. JavaScript was created in 1995 by Brendan Eich at Netscape in just 10 days. The language needed to be simple enough for amateur developers while powerful enough for professional use.

2.1 Influences and Design Decisions

JavaScript was influenced by several languages:

  • Self: For its prototype-based object system
  • Scheme: For first-class functions and functional programming aspects
  • Java: For syntax and naming (though the similarities are largely superficial)

The prototype approach was chosen over classical inheritance for several reasons:

Simplicity and Flexibility: Prototypes allow for dynamic object extension and modification at runtime, which was crucial for the dynamic nature of web development.

Minimalist Design: Netscape needed a lightweight language that could run efficiently in browsers with limited resources of the mid-1990s.

Rapid Prototyping: Web developers needed to quickly create and modify objects without the overhead of class definitions.

2.2 Evolution of the Prototype System

JavaScript’s prototype system has evolved significantly:

1995-1997: The initial implementation used simple prototype chains with limited capabilities.

1999: ECMAScript 3 formalized the prototype system and introduced key methods.

2009: ECMAScript 5 brought Object.create(), providing a cleaner way to create objects with specific prototypes.

2015: ES6 introduced class syntax, which works on top of the existing prototype system.

3. Core Concepts Demystified: [[Prototype]], proto, and .prototype

Understanding JavaScript prototypes requires mastering three distinct but related concepts. Confusion between these terms is the primary source of misunderstanding for most developers.

3.1 [[Prototype]]: The Internal Link

[[Prototype]] is an internal property present on all JavaScript objects. It’s not directly accessible in code but represents the actual prototype linkage that forms the inheritance chain.

// The [[Prototype]] is internal and hidden
const animal = { eats: true };
const rabbit = { jumps: true };

// We can't access [[Prototype]] directly
// But we can work with it through methods

According to the ECMAScript specification, [[Prototype]] is “the object from which this object inherits properties.” When a property is accessed on an object, if it’s not found on the object itself, JavaScript follows the [[Prototype]] link to look for the property on the prototype object.

3.2 proto: The Historical Accessor

The __proto__ property (pronounced “dunder proto”) is a legacy accessor that allows getting and setting the [[Prototype]] of an object.

const animal = { eats: true };
const rabbit = { jumps: true };

// Setting prototype using __proto__ (not recommended)
rabbit.__proto__ = animal;

console.log(rabbit.eats); // true (inherited)
console.log(rabbit.__proto__ === animal); // true

Important Considerations:

  • __proto__ is deprecated and exists mainly for historical reasons
  • It’s not part of the ECMAScript standard until ES6, where it was standardized for web compatibility
  • Modern code should use Object.getPrototypeOf() and Object.setPrototypeOf() instead
  • __proto__ can be a performance bottleneck and isn’t available in all environments

3.3 .prototype: The Constructor Property

The .prototype property exists only on functions (specifically, functions that are intended to be used as constructors). This is arguably the most confusing aspect of JavaScript’s prototype system.

function Animal(name) {
  this.name = name;
}

// The .prototype property of the constructor function
Animal.prototype.speak = function() {
  console.log(`${this.name} makes a sound.`);
};

const dog = new Animal('Rex');
console.log(dog.name); // "Rex" (own property)
dog.speak(); // "Rex makes a sound." (inherited)

// The relationship:
console.log(Object.getPrototypeOf(dog) === Animal.prototype); // true

Key Points about .prototype:

  • Only functions have a .prototype property
  • When a function is used as a constructor with new, the new object’s [[Prototype]] is set to the function’s .prototype
  • The .prototype object typically contains methods and properties that should be shared across all instances

3.4 Comparative Analysis

The table below summarizes the key differences:

Aspect[[Prototype]]proto.prototype
TypeInternal propertyAccessor propertyRegular property
Exists OnAll objectsAll objectsFunctions only
PurposeInternal inheritance linkLegacy access to prototypeConstructor’s prototype
StandardECMAScript specDeprecated but standardizedECMAScript spec
Modern AlternativeN/A (internal)Object.getPrototypeOf()N/A (still used)

4. The Prototype Chain: Understanding Property Resolution

The prototype chain is JavaScript’s mechanism for property lookup. Understanding this chain is crucial for effective debugging and performance optimization.

4.1 How Property Lookup Works

When you access a property on an object, JavaScript follows a specific lookup process:

const grandparent = { a: 1 };
const parent = { b: 2 };
const child = { c: 3 };

// Set up the prototype chain
Object.setPrototypeOf(parent, grandparent);
Object.setPrototypeOf(child, parent);

// The chain: child -> parent -> grandparent -> Object.prototype -> null

console.log(child.c); // 3 (own property)
console.log(child.b); // 2 (inherited from parent)
console.log(child.a); // 1 (inherited from grandparent)
console.log(child.toString); // function (inherited from Object.prototype)
console.log(child.nonExistent); // undefined (not found)

The lookup algorithm follows these steps:

  1. Check if the property exists on the object itself
  2. If not, follow the [[Prototype]] link to the prototype object and repeat
  3. Continue until the property is found or the chain ends with null
  4. Return undefined if the property is never found

4.2 Property Shadowing and Method Overriding

When a property with the same name exists on both an object and its prototype, the object’s own property “shadows” the prototype’s property.

const animal = {
  eats: true,
  sleep() {
    return 'Animal sleeping';
  }
};

const rabbit = {
  jumps: true,
  sleep() {
    return 'Rabbit sleeping quietly';
  }
};

Object.setPrototypeOf(rabbit, animal);

console.log(rabbit.sleep()); // "Rabbit sleeping quietly" (shadowing)
console.log(rabbit.eats); // true (inherited)

4.3 The Ultimate Prototype: Object.prototype

Almost all objects in JavaScript eventually inherit from Object.prototype, which provides fundamental methods like:

  • toString()
  • valueOf()
  • hasOwnProperty()
  • isPrototypeOf()
  • propertyIsEnumerable()
const obj = { x: 1 };
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype)); // null

Objects created with Object.create(null) are exceptions—they have no prototype and don’t inherit from Object.prototype.

5. Implementing Inheritance: Multiple Approaches Compared

JavaScript provides several patterns for implementing inheritance, each with its own strengths and use cases.

5.1 Functional Pattern with Object.create()

This pattern uses factory functions and Object.create() for clean, flexible inheritance.

// Base object prototype
const animal = {
  init(name) {
    this.name = name;
    return this;
  },
  speak() {
    return `${this.name} makes a sound.`;
  }
};

// Create specialized objects
const dog = Object.create(animal);
dog.bark = function() {
  return `${this.name} barks loudly!`;
};
dog.speak = function() { // Override
  return this.bark();
};

const cat = Object.create(animal);
cat.meow = function() {
  return `${this.name} meows softly.`;
};
cat.speak = function() { // Override
  return this.meow();
};

// Usage
const rex = Object.create(dog).init('Rex');
const whiskers = Object.create(cat).init('Whiskers');

console.log(rex.speak()); // "Rex barks loudly!"
console.log(whiskers.speak()); // "Whiskers meows softly."

5.2 Constructor Pattern

The traditional constructor pattern uses functions and the new keyword.

function Animal(name) {
  this.name = name;
  this.eats = true;
  this.sleeps = true;
}

Animal.prototype.speak = function() {
  return `${this.name} makes a sound.`;
};

Animal.prototype.sleep = function() {
  return `${this.name} is sleeping.`;
};

function Dog(name, breed) {
  Animal.call(this, name); // Call parent constructor
  this.breed = breed;
}

// Set up inheritance
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // Fix constructor reference

Dog.prototype.bark = function() {
  return `${this.name} barks!`;
};

Dog.prototype.speak = function() { // Override
  return this.bark();
};

// Usage
const rex = new Dog('Rex', 'German Shepherd');
console.log(rex.speak()); // "Rex barks!"
console.log(rex.sleep()); // "Rex is sleeping." (inherited)
console.log(rex instanceof Dog); // true
console.log(rex instanceof Animal); // true

5.3 Parasitic Inheritance

A pattern that enhances objects by creating them based on existing instances.

function createAnimal(name) {
  const animal = { name };
  
  animal.speak = function() {
    return `${this.name} makes a sound.`;
  };
  
  animal.eat = function() {
    return `${this.name} is eating.`;
  };
  
  return animal;
}

function createDog(name, breed) {
  const dog = createAnimal(name); // "Parasitize" base object
  dog.breed = breed;
  
  const originalSpeak = dog.speak;
  dog.speak = function() {
    return `${originalSpeak.call(this)} But it also barks!`;
  };
  
  dog.fetch = function() {
    return `${this.name} fetches the ball.`;
  };
  
  return dog;
}

// Usage
const rex = createDog('Rex', 'Labrador');
console.log(rex.speak()); // "Rex makes a sound. But it also barks!"
console.log(rex.fetch()); // "Rex fetches the ball."

6. Constructor Functions: The Classical Pattern

Constructor functions represent the most traditional approach to JavaScript inheritance and form the basis for ES6 classes.

6.1 The new Keyword Mechanism

When you call a function with new, four things happen:

function Animal(name) {
  // 1. A new object is created: {}
  // 2. this is bound to the new object
  // 3. The [[Prototype]] is set to Animal.prototype
  this.name = name;
  this.eats = true;
  
  // 4. The function executes, and if it doesn't return an object,
  // the new object is returned
}

// What happens with new Animal('Rex'):
const rex = new Animal('Rex');

We can simulate the new operator to understand it better:

function simulateNew(constructor, ...args) {
  // 1. Create new object with constructor's prototype
  const obj = Object.create(constructor.prototype);
  
  // 2. Execute constructor with obj as this
  const result = constructor.apply(obj, args);
  
  // 3. Return object (or result if it's an object)
  return result instanceof Object ? result : obj;
}

// Equivalent usage:
const rex1 = new Animal('Rex');
const rex2 = simulateNew(Animal, 'Rex');
console.log(rex1.name === rex2.name); // true

6.2 Constructor Inheritance Patterns

Several patterns have emerged for inheritance with constructors:

Classical Inheritance Pattern:

function Parent(name) {
  this.name = name;
}

Parent.prototype.speak = function() {
  return `Hello, I'm ${this.name}`;
};

function Child(name, age) {
  Parent.call(this, name); // Inherit instance properties
  this.age = age;
}

// Inherit prototype methods
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

Child.prototype.getAge = function() {
  return this.age;
};

Intermediate Function Pattern:

function extend(Child, Parent) {
  // Create temporary constructor to avoid calling Parent constructor
  var F = function() {};
  F.prototype = Parent.prototype;
  Child.prototype = new F();
  Child.prototype.constructor = Child;
  Child.super = Parent.prototype; // Reference to parent prototype
}

// Usage
function Child(name, age) {
  Parent.call(this, name);
  this.age = age;
}
extend(Child, Parent);

7. Object.create(): The Pure Prototypal Approach 

Object.create(), introduced in ES5, provides a clean way to create objects with specified prototypes without using constructor functions.

7.1 Understanding Object.create()

The method signature is straightforward:

Object.create(proto, [propertiesObject])
  • proto: The object which should be the prototype of the newly-created object
  • propertiesObject (optional): Property descriptors to add to the new object
const animal = {
  speak() {
    return 'Some sound';
  }
};

// Simple inheritance
const dog = Object.create(animal);
dog.bark = function() {
  return 'Woof!';
};

// With property descriptors
const cat = Object.create(animal, {
  name: {
    value: 'Whiskers',
    writable: true,
    enumerable: true,
    configurable: true
  },
  meow: {
    value: function() { return 'Meow!'; },
    enumerable: true
  }
});

7.2 Advanced Object.create() Patterns

Mixin Pattern with Object.create():

const canEat = {
  eat(food) {
    return `${this.name} eats ${food}.`;
  }
};

const canSleep = {
  sleep() {
    return `${this.name} is sleeping.`;
  }
};

function createAnimal(name) {
  const animal = Object.create({
    ...canEat,
    ...canSleep
  });
  animal.name = name;
  return animal;
}

const rex = createAnimal('Rex');
console.log(rex.eat('bone')); // "Rex eats bone."
console.log(rex.sleep()); // "Rex is sleeping."

Composition Over Inheritance:

// Instead of deep inheritance hierarchies, compose objects
const behaviors = {
  eater() {
    return {
      eat(food) {
        return `${this.name} eats ${food}`;
      }
    };
  },
  
  sleeper() {
    return {
      sleep() {
        return `${this.name} sleeps`;
      }
    };
  },
  
  player() {
    return {
      play() {
        return `${this.name} plays`;
      }
    };
  }
};

function createDog(name) {
  const dog = Object.create({
    ...behaviors.eater(),
    ...behaviors.sleeper(),
    ...behaviors.player(),
    bark() {
      return 'Woof!';
    }
  });
  dog.name = name;
  return dog;
}

8. ES6 Classes: Syntactic Sugar Demystified

ES6 classes provide a cleaner syntax for working with prototypes, but they don’t change how JavaScript inheritance works under the hood.

8.1 Class Syntax vs Prototype Reality

Let’s compare class syntax with its prototype equivalent:

// ES6 Class
class Animal {
  constructor(name) {
    this.name = name;
    this.eats = true;
  }
  
  speak() {
    return `${this.name} makes a sound.`;
  }
  
  static isAnimal(obj) {
    return obj instanceof Animal;
  }
}

// Equivalent prototype code
function Animal(name) {
  this.name = name;
  this.eats = true;
}

Animal.prototype.speak = function() {
  return `${this.name} makes a sound.`;
};

Animal.isAnimal = function(obj) {
  return obj instanceof Animal;
};

8.2 Inheritance with extends

The extends keyword simplifies prototype chain setup:

class Animal {
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    return `${this.name} makes a sound.`;
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // Must call super before using this
    this.breed = breed;
  }
  
  speak() { // Method override
    return `${super.speak()} But it barks!`;
  }
  
  fetch() {
    return `${this.name} fetches the ball.`;
  }
}

// Under the hood, this sets up:
// Dog.prototype.__proto__ = Animal.prototype

8.3 What Classes Don’t Change

Despite the cleaner syntax, classes maintain JavaScript’s prototypal nature:

  • No real classes: Still prototype-based inheritance
  • No private fields (until recent additions)
  • Methods are still on the prototype:javascriptclass Animal { speak() { /* … */ } } const animal = new Animal(); console.log(animal.hasOwnProperty(‘speak’)); // false console.log(Animal.prototype.hasOwnProperty(‘speak’)); // true
  • Dynamic modification still possible:javascriptclass Animal { speak() { return ‘Original’; } } // You can still modify the prototype Animal.prototype.speak = function() { return ‘Modified’; }; const animal = new Animal(); console.log(animal.speak()); // “Modified”

9. Advanced Patterns and Techniques

9.1 Multiple Inheritance Simulation

While JavaScript doesn’t support multiple inheritance directly, we can simulate it:

// Mixin pattern
const CanFly = {
  fly() {
    return `${this.name} flies.`;
  }
};

const CanSwim = {
  swim() {
    return `${this.name} swims.`;
  }
};

class Animal {
  constructor(name) {
    this.name = name;
  }
}

// Apply mixins
Object.assign(Animal.prototype, CanFly, CanSwim);

class Duck extends Animal {
  quack() {
    return 'Quack!';
  }
}

const donald = new Duck('Donald');
console.log(donald.fly()); // "Donald flies."
console.log(donald.swim()); // "Donald swims."

9.2 Factory Functions with Composition

Factory functions provide an alternative to constructor-based inheritance:

const createSpeaker = (state) => ({
  speak: () => `My name is ${state.name}`
});

const createWalker = (state) => ({
  walk: () => `${state.name} is walking`
});

const createEater = (state) => ({
  eat: (food) => `${state.name} eats ${food}`
});

function createPerson(name) {
  const state = { name };
  
  return {
    ...state,
    ...createSpeaker(state),
    ...createWalker(state),
    ...createEater(state)
  };
}

const john = createPerson('John');
console.log(john.speak()); // "My name is John"
console.log(john.eat('pizza')); // "John eats pizza"

9.3 Proxy-based Prototype Manipulation

ES6 Proxies allow advanced prototype manipulation:

function createPrototypeChain(...prototypes) {
  return prototypes.reduceRight((child, parent) => {
    return new Proxy(child, {
      get(target, property, receiver) {
        // Check child first, then parent
        if (property in target) {
          return target[property];
        }
        return parent[property];
      },
      has(target, property) {
        return property in target || property in parent;
      }
    });
  });
}

const animal = { eats: true };
const mammal = { warmBlooded: true };
const dog = { barks: true };

const advancedDog = createPrototypeChain(dog, mammal, animal);
console.log(advancedDog.eats); // true
console.log(advancedDog.warmBlooded); // true
console.log(advancedDog.barks); // true

10. Performance Considerations and Best Practices

10.1 Prototype Chain Performance

The prototype chain lookup has performance implications:

Optimized Lookups: Modern JavaScript engines optimize prototype chain lookups using hidden classes and inline caches.

Performance Pitfalls:

// SLOW: Dynamic property addition after object creation
function Animal() {}
const animal = new Animal();
animal.newMethod = function() { /* ... */ }; // Changes hidden class

// FAST: All properties defined in constructor or prototype
function Animal() {
  this.consistentlyAdded = true;
}
Animal.prototype.consistentlyAddedMethod = function() { /* ... */ };

10.2 Memory Efficiency

Prototypes provide significant memory benefits:

// Without prototypes - each instance gets its own method copies
function Animal(name) {
  this.name = name;
  this.speak = function() { return 'Sound'; }; // New function for each instance!
}

// With prototypes - methods are shared
function Animal(name) {
  this.name = name;
}
Animal.prototype.speak = function() { return 'Sound'; }; // Shared across instances

10.3 Best Practices

  1. Prefer Object.create() for pure prototypal inheritance
  2. Use constructor functions when you need instance-specific state
  3. Avoid deep inheritance hierarchies – favor composition
  4. Don’t modify built-in prototypes (Array.prototype, Object.prototype, etc.)
  5. Use Object.freeze() on shared prototypes to prevent accidental modifications
  6. Be cautious with dynamic prototype changes in performance-critical code

11. Real-World Applications and Case Studies

11.1 Framework and Library Examples

React Component Inheritance:

// Base component with common functionality
class BaseComponent extends React.Component {
  trackEvent(eventName, data) {
    analytics.track(eventName, data);
  }
  
  handleError(error) {
    this.setState({ error });
    this.trackEvent('error', { error: error.message });
  }
}

// Specialized component
class UserProfile extends BaseComponent {
  async componentDidMount() {
    try {
      const user = await fetchUser(this.props.userId);
      this.setState({ user });
    } catch (error) {
      this.handleError(error); // Inherited method
    }
  }
}

Vue.js Mixin Pattern:

// Vue uses prototype-based inheritance for components
const fetchMixin = {
  methods: {
    async $fetch(url) {
      this.loading = true;
      try {
        const response = await fetch(url);
        return await response.json();
      } finally {
        this.loading = false;
      }
    }
  }
};

// Usage in component
const UserComponent = {
  mixins: [fetchMixin],
  async created() {
    this.user = await this.$fetch('/api/user');
  }
};

11.2 Node.js Built-in Modules

Many Node.js core modules use prototype-based patterns:

const EventEmitter = require('events');

// Traditional constructor pattern
class MyEmitter extends EventEmitter {
  constructor() {
    super();
  }
}

// Underlying prototype setup:
// MyEmitter.prototype.__proto__ = EventEmitter.prototype

12. Common Pitfalls and How to Avoid Them

12.1 Constructor Property Issues

Forgetting to reset the constructor property:

function Animal() {}
function Dog() {}

Dog.prototype = Object.create(Animal.prototype);
// Missing: Dog.prototype.constructor = Dog;

console.log(new Dog().constructor === Animal); // true (wrong!)
console.log(new Dog().constructor === Dog); // false

Solution: Always reset the constructor property after setting up inheritance.

12.2 Shadowing Built-in Methods

Accidentally shadowing Object.prototype methods:

const obj = {
  hasOwnProperty: 'oops' // Shadows Object.prototype.hasOwnProperty
};

// This will throw an error:
// obj.hasOwnProperty('prop'); // TypeError: obj.hasOwnProperty is not a function

// Safe access:
Object.prototype.hasOwnProperty.call(obj, 'prop');

12.3 Circular Prototype Chains

Creating circular references (though modern JavaScript prevents this):

const obj1 = {};
const obj2 = {};

// This will throw in strict mode or fail silently
Object.setPrototypeOf(obj1, obj2);
// Object.setPrototypeOf(obj2, obj1); // TypeError: Cyclic __proto__ value

13. The Future of JavaScript Objects

13.1 Private Fields and Methods

ES2022 introduced truly private fields and methods:

class Animal {
  #privateField = 'secret'; // Truly private
  
  #privateMethod() {
    return this.#privateField;
  }
  
  // These are NOT on the prototype
  getSecret() {
    return this.#privateMethod();
  }
}

const animal = new Animal();
console.log(animal.#privateField); // SyntaxError
console.log(animal.getSecret()); // "secret"

13.2 Decorators (Stage 3 Proposal)

Decorators will provide metadata and modification capabilities:

@sealed
class Animal {
  @readonly
  species = 'mammal';
  
  @log
  speak() {
    return 'Sound';
  }
}

13.3 Records and Tuples (Proposal)

Immutable data structures that might change how we think about object relationships:

// Proposal: Records and Tuples
const record = #{
  name: "John",
  profile: #{
    age: 30
  }
};

14. Conclusion

JavaScript’s prototypal inheritance model is a powerful, flexible system that differs fundamentally from class-based inheritance. While ES6 classes provide a familiar syntax, they build upon the same prototype system that has existed since JavaScript’s creation.

Key Takeaways:

  1. Prototypes are fundamental: Everything in JavaScript that isn’t a primitive inherits from Object.prototype (except objects created with Object.create(null)).
  2. Multiple patterns exist: Constructor functions, Object.create(), factory functions, and classes all use prototypes under the hood.
  3. Performance matters: Understanding prototype chains helps write performant code by leveraging shared methods and avoiding hidden class changes.
  4. Composition over inheritance: Modern JavaScript often favors object composition through mixins and factory functions over deep inheritance hierarchies.
  5. The future is evolving: Private fields, decorators, and new data structures continue to enhance JavaScript’s object capabilities while maintaining prototype compatibility.

Mastering prototypes is not just about understanding a language feature—it’s about embracing JavaScript’s unique approach to object-oriented programming. This understanding enables developers to write more efficient, maintainable code and to leverage the full power of one of the world’s most popular programming languages.

15. References

  1. ECMAScript® 2025 Language Specification – The official ECMAScript specification
  2. MDN Web Docs: Inheritance and the prototype chain – Comprehensive guide with examples
  3. JavaScript: The Definitive Guide, 7th Edition – David Flanagan’s authoritative reference
  4. You Don’t Know JS Yet: Objects & Classes – In-depth exploration of JavaScript objects
  5. Prototypal Inheritance in JavaScript – Modern tutorial with interactive examples
  6. Brendan Eich: JavaScript at 20 – Historical context from JavaScript’s creator
  7. V8 Engine Documentation: Fast Properties – How V8 optimizes property access
  8. Composition Over Inheritance – React’s perspective on object composition
  9. TC39 Proposals – Upcoming JavaScript features
  10. JavaScript Engine Fundamentals: Shapes and Inline Caches – Deep dive into JavaScript engine optimization