Slide 1

Slide 1 text

Understanding JS prototypes Sebastian Porto

Slide 2

Slide 2 text

+ Prototypes ! + Object.create ! + Constructor functions ! + ES6

Slide 3

Slide 3 text

The wrong way to learn function Liquid() { } Liquid.prototype.fluid = true; ! function Beer() { Liquid.call(this); } ! Beer.prototype = Object.create(Liquid.prototype); Beer.prototype.alcohol = 5.1; ! var beer = new Beer();

Slide 4

Slide 4 text

__proto__

Slide 5

Slide 5 text

• var liquid = {}
 var beer = {} • beer.__proto__ = liquid A simple chain

Slide 6

Slide 6 text

A simple chain liquid beer __proto__ liquid is the prototype of beer

Slide 7

Slide 7 text

Property look-ups • var liquid = {
 fluid: true
 } • var beer = {}
 beer.__proto__ = liquid • beer.fluid //-> true

Slide 8

Slide 8 text

A simple chain liquid beer __proto__ fluid fluid? fluid?

Slide 9

Slide 9 text

A longer chain liquid coopers fluid fluid? beer drink

Slide 10

Slide 10 text

Long chain example • var liquid = { fluid: true } • var drink = {}
 drink.__proto__ = liquid • var beer = {}
 beer.__proto__ = drink • var coopers = {}
 coopers.__proto__ = beer • coopers.fluid; //-> true

Slide 11

Slide 11 text

Many object can have same prototype liquid beer __proto__ cider __proto__

Slide 12

Slide 12 text

Prototype can be shared • var liquid = { fluid: true } • var beer = {}
 beer.__proto__ = liquid • var cider = {}
 cider.__proto__ = liquid • beer.fluid; //-> true
 cider.fluid; //-> true

Slide 13

Slide 13 text

Prototypes are not copies • var beer = { tasty: true }; • var coopers = {};
 coopers.__proto__ = beer; • coopers.tasty; //-> true • beer.tasty = false; • cooper.tasty; //-> false

Slide 14

Slide 14 text

beer coopers ethanol Prototypes are dynamic .__proto__

Slide 15

Slide 15 text

Prototypes are dynamic • var beer = { alcohol: 6 }
 var ethanol = { alcohol: 100 } • var coopers = {}
 coopers.__proto__ = beer • coopers.alcohol //-> 6 • coopers.__proto__ = ethanol • coopers.alcohol //-> 100

Slide 16

Slide 16 text

Writing creates properties • var beer = { alcohol: 6 } • var coopers = {}
 coopers.__proto__ = beer • coopers.alcohol = 4 • beer.alcohol //-> still 6

Slide 17

Slide 17 text

Creates ‘own’ property beer coopers alcohol = 6 .alcohol = 4 alcohol = 4 “own” property

Slide 18

Slide 18 text

beer coopers alcohol = 6 alcohol = 4 creatures Same property can be in several places

Slide 19

Slide 19 text

Arrays • var beer = { 
 ingredients: [‘wheat’, ‘yeast’] 
 } • var coopers = {}
 coopers.__proto__ = beer • coopers.ingredients.push(‘oats’) • beer.ingredients
 //->[‘wheat’, ‘yeast’, ‘oats’];

Slide 20

Slide 20 text

Direct modification beer coopers ingredients .ingredients.push(‘oats’)

Slide 21

Slide 21 text

coopers.ingredients.push(‘oats’); ! creatures.ingredients; //-> [‘wheat’, ‘yeast’, ‘oats’]; Arrays are modified directly in the prototype beer coopers creatures ingredients ['wheat', 'yeast'] __proto__ __proto__

Slide 22

Slide 22 text

Objects are the same • var beer = { 
 ingredients: {wheat: 10, yeast: 20} 
 } • var coopers = {}
 coopers.__proto__ = beer • coopers.ingredients.wheat = 30 • beer.ingredients.wheat
 //-> 30

Slide 23

Slide 23 text

__proto__ == great for learning ! Not for use

Slide 24

Slide 24 text

Object.create

Slide 25

Slide 25 text

Object.create • var beer = { 
 tasty: true
 } • var coopers = Object.create(beer) • coopers.tasty //-> true

Slide 26

Slide 26 text

Object.create var coopers = Object.create(beer); ! Just like: ! var coopers = {}; coopers.__proto__ = beer;

Slide 27

Slide 27 text

Object.create is just setting __proto__ ! so same rules apply - not copies - dynamic

Slide 28

Slide 28 text

getPrototypeOf var beer = { tasty: true }; ! var coopers = Object.create(beer); ! ! Object.getPrototypeOf(coopers) //-> beer object

Slide 29

Slide 29 text

isPrototypeOf var beer = { tasty: true }; ! var coopers = Object.create(beer); ! ! beer.isPrototypeOf(coopers); //-> true

Slide 30

Slide 30 text

ES6 setPrototypeOf var beer = { tasty: true }; ! var coopers = {}; ! ! Object.setPrototypeOf(coopers, beer);

Slide 31

Slide 31 text

Constructor Functions

Slide 32

Slide 32 text

Functions as constructors function Beer(){ ! } ! var beer = new Beer(); Uppercase by convention

Slide 33

Slide 33 text

function Beer(){ ! ! ! ! ! } ! var beer = new Beer(); Implicit this ! var this = {} this.__proto__ = Beer.prototype (yield to your code) return this

Slide 34

Slide 34 text

Implicit this function Beer(){ var this = {}; this.__proto__ = Beer.prototype; this.tasty = true; return this; } ! var beer = new Beer(); ! beer.tasty; // true

Slide 35

Slide 35 text

function Beer(){ this.tasty = true; } ! var beer = new Beer(); ! beer.tasty; //-> true Implicit this

Slide 36

Slide 36 text

Don’t forget new function Beer(){ this.kind = ‘beer’; } ! var beer = Beer(); this will the global object

Slide 37

Slide 37 text

function Beer(){ ! this.__proto__ = Beer.prototype; ! } function.prototype

Slide 38

Slide 38 text

function.prototype function Beer(){ ! } ! Beer.prototype Every function has this special property

Slide 39

Slide 39 text

But this is not the prototype Beer.prototype !== Beer.__proto__ Call this ‘function prototype’

Slide 40

Slide 40 text

function.prototype function Beer(){ ! } ! var beer = new Beer(); beer.__proto__ ???? What is the __proto__ of beer?

Slide 41

Slide 41 text

It is assigned as the prototype of the instance function Beer(){ var this = {}; this.__proto__ = Beer.prototype; this.tasty = true; return this; } It is assigned as the prototype of the new created object

Slide 42

Slide 42 text

Function instance new __proto__ Function prototype .prototype

Slide 43

Slide 43 text

• function Beer(){} • Beer.prototype.tasty = true • var coopers = new Beer() • coopers.__proto__ == Beer.prototype
 //-> true • coopers.tasty //-> true It is the prototype assigned to the instance

Slide 44

Slide 44 text

function Beer(){ } ! Beer.prototype.brew = function () {} ! var coopers = new Beer(); var creatures = new Beer(); ! coopers.brew(); creatures.brew(); ! Useful for performance

Slide 45

Slide 45 text

• function Beer(){...} • Beer.prototype.ingredients = ['honey'] • var coopers = new Beer()
 var vb = new Beer() • coopers.ingredients.push('oats') • vb.ingredients //-> ['honey', 'oats'] Again, same rules!

Slide 46

Slide 46 text

• function Beer(){
 this.ingredients = [‘yeast’]
 } • var coopers = new Beer()
 var creatures = new Beer() • coopers.ingredients.push(‘wheat’) • creatures.ingredients
 //-> [‘yeast’] Isolation

Slide 47

Slide 47 text

function Beer(){ ! } ! var coopers = new Beer(); ! coopers instanceof Beer; //-> true ! instanceof

Slide 48

Slide 48 text

coopers instanceof Beer; ! ! Checks that ! coopers.__proto__ == Beer.prototype ! instanceof

Slide 49

Slide 49 text

var Beer = function () { ! }; ! Beer.findAll = function () { ... } ! Beer.findAll(); "Class methods"

Slide 50

Slide 50 text

ES6

Slide 51

Slide 51 text

class Beer { constructor(a) { this.alcohol = a; } ! drink() { ... } } ES6 Classes

Slide 52

Slide 52 text

ES6 Classes function Beer(a){ this.alcohol = a; } ! Beer.prototype.drink = function () { ... } ! var beer = new Beer(5) class Beer { constructor(a) { this.alcohol = a; } ! drink() { ... } } ! var beer = new Beer(5)

Slide 53

Slide 53 text

Questions? Thanks