Skip to content

Instantly share code, notes, and snippets.

@gaearon
Created May 27, 2020 17:38
Show Gist options
  • 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.

@duzitug
Copy link

duzitug 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.

@magnusram05
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?

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.

This someFunction.prototype.__proto__ === everyObjectProto; // true can be changed to someFunction.prototype === everyObjectProto; // false for clarity

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