What it does: Built-in JavaScript objects (Array, Object, String, etc.) use prototypes to give you all those methods you use daily.

How Built-in Objects Actually Work:

Where Your Methods Come From:

javascript

let obj = {}; // Same as: new Object()
obj.toString(); // "[object Object]"
 
// Where did toString come from?
console.log(obj.__proto__ === Object.prototype); // true
console.log(obj.toString === Object.prototype.toString); // true

The Built-in Prototype Chain:

javascript

let arr = [1, 2, 3]; // Same as: new Array(1, 2, 3)
 
// Chain: arr → Array.prototype → Object.prototype → null
console.log(arr.__proto__ === Array.prototype); // true
console.log(arr.__proto__.__proto__ === Object.prototype); // true
console.log(arr.__proto__.__proto__.__proto__); // null
 
arr.push(4); // Method from Array.prototype
arr.toString(); // "1,2,3" (Array.prototype.toString, not Object's)

Functions Are Objects Too:

javascript

function myFunc() {}
 
console.log(myFunc.__proto__ === Function.prototype); // true
console.log(myFunc.__proto__.__proto__ === Object.prototype); // true
 
myFunc.call(); // Method from Function.prototype

How Primitives Get Methods:

Temporary Wrapper Objects:

javascript

"hello".toUpperCase(); // How does a string have methods?
 
// JavaScript secretly does this:
// 1. Creates: new String("hello")  
// 2. Calls: tempStringObj.toUpperCase()
// 3. Returns result and destroys temp object
 
console.log("hello".__proto__ === String.prototype); // true

The Memory-Efficient System:

javascript

// All arrays share the SAME Array.prototype object in memory
let arr1 = [1, 2];
let arr2 = [3, 4];
console.log(arr1.__proto__ === arr2.__proto__); // true (same memory address!)

The Universal Chain:

Everything Inherits from Object:

javascript

// Array → Object
console.log(Array.prototype.__proto__ === Object.prototype); // true
 
// String → Object  
console.log(String.prototype.__proto__ === Object.prototype); // true
 
// Function → Object
console.log(Function.prototype.__proto__ === Object.prototype); // true
 
// Object is the top
console.log(Object.prototype.__proto__); // null

Interview Gotchas:

javascript

// Gotcha 1: Method shadowing - closer prototype wins
let arr = [1, 2, 3];
arr.toString(); // "1,2,3" (Array.prototype.toString)
// NOT "[object Array]" (Object.prototype.toString)
 
// Gotcha 2: Primitives can't store properties
let str = "hello";
str.newProp = "test";
console.log(str.newProp); // undefined (wrapper object destroyed!)
 
// Gotcha 3: null and undefined have no prototypes
console.log(null.__proto__); // TypeError!
console.log(undefined.toString); // TypeError!
 
// Gotcha 4: Modifying native prototypes affects EVERYTHING
String.prototype.shout = function() { return this.toUpperCase(); };
"hello".shout(); // "HELLO" 
"world".shout(); // "WORLD" (all strings get it!)

Method Borrowing:

Stealing Array Methods:

javascript

let arrayLike = {
  0: "a",
  1: "b", 
  length: 2
};
 
// Borrow Array's join method
arrayLike.join = Array.prototype.join;
console.log(arrayLike.join("-")); // "a-b"
 
// Or call it directly
let result = Array.prototype.slice.call(arrayLike);
console.log(result); // ["a", "b"]

Never Get Tricked - Follow These Rules:

  1. Memory sharing - All instances share the same prototype object
  2. Chain lookup - Closer prototype methods win over farther ones
  3. Primitives get temporary wrappers - can’t store custom properties
  4. Don’t modify native prototypes - unless polyfilling missing features
  5. Method borrowing works - if the method only needs indexes/length

Bottom line: JavaScript gives you built-in methods through a shared prototype system where everything ultimately inherits from Object, making the language memory-efficient but powerful.