Skip to content

Instantly share code, notes, and snippets.

@gaearon
Created May 27, 2020 17:38
Show Gist options
  • Star 108 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save gaearon/a25fd42a1e6b4cc24851978df0a36571 to your computer and use it in GitHub Desktop.
Save gaearon/a25fd42a1e6b4cc24851978df0a36571 to your computer and use it in GitHub Desktop.
Beneath Classes: Prototypes
class Spiderman {
lookOut() {
alert('My Spider-Sense is tingling.');
}
}
let miles = new Spiderman();
miles.lookOut();
// class Spiderman {
let SpidermanPrototype = {
lookOut() {
alert('My Spider-Sense is tingling.');
}
};
// let miles = new Spiderman();
let miles = { __proto__: SpidermanPrototype };
miles.lookOut();
@aquibyatoo
Copy link

let miles = Object.create(SpidermanPrototype)

@timiscoding
Copy link

function Spiderman() {}
Spiderman.prototype.lookOut = function() {
  alert('My Spider-Sense is tingling.');
}

Same?

@rafaelcastrocouto
Copy link

rafaelcastrocouto commented May 28, 2020

function Spiderman() {
  this.__proto__.lookOut = function() {
    alert('My Spider-Sense is tingling.');
  }
}
let miles = new Spiderman();

@rahildar
Copy link

Hi @rafaelcastrocouto miles instanceof Spiderman would be false if replaced completely.

@rafaelcastrocouto
Copy link

Thanks for the comment @rahildar! I've fixed it, check out the edit.

@mabdullahsari
Copy link

mabdullahsari commented May 31, 2020

@timiscoding

function Spiderman() {}
Spiderman.prototype.lookOut = function() {
  alert('My Spider-Sense is tingling.');
}

Same?

Not really unless you use the new operator (new Spiderman). Under the hood, 4 things happen:

  • A brand new object is created
  • That object's prototype is set to the prototype property of the function you're newing up.
  • The "constructor" function (ie. Spiderman) is called with the "this" context set to the brand new object in step 1.
  • The brand new object in step 1 is returned (there is an edge case but it's something dumb).

Dan's example is the simplest and the most accurate though, imo.

@front-end-performer
Copy link

front-end-performer commented May 31, 2020

`
// class Spiderman {
let SpidermanPrototype = {
lookOut() {
alert('My Spider-Sense is tingling.');
}
};

// let miles = new Spiderman();
let miles = { proto: SpidermanPrototype };
miles.lookOut();
`

Alot more clear for my head to remember...

@timiscoding
Copy link

@abdullahsari thanks, that jogged my memory. I remember reading that in YDKJS.

Did a bit more digging as the code I had written was something I remembered a long time ago. See YDKJS

I was curious how TypeScript/babel transpile classes and discovered they pretty much use the same method except babel does more checking and property descriptor setting.

TypeScript playground

Babel playground

@quintontcampbell
Copy link

Love this content, thank you for sharing it freely with us all Dan!

@ovistoica
Copy link

image

This is picked up from the Typescript playground. I just finished the Just Javascript module written by Dan and I have a question which might be a noob one but isn't Spiderman.prototype.lookOut = (..) regarded as polluting the prototype and should be discouraged?

@haikyuu
Copy link

haikyuu commented Aug 19, 2021

@ovistoica typescript is probably converting it like that for compatibility and performance reasons. But people are discouraged to use it.

@merciof
Copy link

merciof commented Jan 29, 2022

@ovistoica I think it is not exactly polluting, because It isn't changing a default prototype like Array, String or Object ones.

@khoanguyen-yang
Copy link

Hi @gaearon,

I am wondering why, when defining classes, the properties are on the object itself while the methods are on the __proto__

class Spiderman {
  aProperty;
  lookOut() {
    alert("My Spider-Sense is tingling.");
  }
}

let miles = new Spiderman();
console.log(miles.hasOwnProperty("aProperty")); // true
console.log(Object.getPrototypeOf(miles).hasOwnProperty("lookOut")); // true

@buza-me
Copy link

buza-me commented Jun 14, 2023

image

This is picked up from the Typescript playground. I just finished the Just Javascript module written by Dan and I have a question which might be a noob one but isn't Spiderman.prototype.lookOut = (..) regarded as polluting the prototype and should be discouraged?

const someObject = {};
const everyObjectProto = someObject.__proto__;
const someFunction = function() {};
someFunction.prototype.__proto__ === everyObjectProto; // true

So "someFunction.prototype" points to an object, just like any other in your code, not to the "main" object prototype. Thus it is not polluting anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment