Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Animal
.arguments
.name
Animal.prototype
.poop()
Dog
.arguments
.name
Dog.prototype
.bark()
fido
build data object
lassie
build data object
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
{ }, constructor functions, factory functions
Object.create(), class
Prototype chains
Inheritance - traditional and modern
Instantiation with new
Composition with Object.assign()
TC39
Brendan Eich
@brendaneich
Douglas Crockford
crockford.com
Kyle Simpson
@getify
Eric Elliott
@_ericelliott
Mattias Johansson
@mpjme
Manual
Object literal
{ }
Automated
constructor functions
& new
also:
factory functions
(discuss later)
Manual
Object literal
{ }
Automated
constructor functions
& new
var fido = {
name: 'Fido',
favoriteThings: ['food', 'fetch'],
bark: function () {...},
howl: function () {...}
};
function Dog(name, faves) {
this.name = name;
this.favoriteThings = faves;
this.bark = function () {...};
this.howl = function () {...};
};
var faves = ['food', 'fetch']
var fido = new Dog('Fido', faves);
var lassie = new Dog('Lassie', faves);
function Dog(name, faves) {
this.name = name;
this.favoriteThings = faves;
};
Dog.prototype.bark = function () {...};
Dog.prototype.howl = function () {...};
var faves = ['food', 'fetch'];
var fido = new Dog('Fido', faves);
var lassie = new Dog('Lassie', faves);
function Animal() {...}
Animal.prototype.poop = function () {...};
function Dog() {
Animal.call(this);
};
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function () {...};
var fido = new Dog(...);
var lassie = new Dog(...);
Object.create()
ES5 (2009)
class, extends
ES6 (2015)
Array
Object
Function
ES5
Array
ArrayBuffer
DataView
EvalError
Float32Array
Float64Array
Int8Array
ReferenceError
Set
Symbol
SyntaxError
TypeError
Uint8Array
Date
Math
Object
Function
String
ES5
ES6
Int16Array
Int32Array
Map
Proxy
Promise
RangeError
Uint8ClampedArray
Uint16Array
Uint32Array
URIError
WeakMap
WeakSet
Number
JSON
Reflect
Boolean
Error
RegExp
Object.prototype
.hasOwnProperty()
.isPrototypeOf()
.propertyIsEnumerable()
.toLocalString()
.toString()
.valueOf()
.__defineGetter__()
.__defineSetter__()
.__lookupGetter__()
.__lookupSetter__()
get __proto__()
set __proto__()
.constructor()
Object.prototype
.hasOwnProperty()
.isPrototypeOf()
.propertyIsEnumerable()
.toLocalString()
.toString()
.valueOf()
.__defineGetter__()
.__defineSetter__()
.__lookupGetter__()
.__lookupSetter__()
get __proto__()
set __proto__()
.constructor()
Object.prototype
.hasOwnProperty()
.toString()
Object.prototype
.hasOwnProperty()
.toString()
Object.prototype
.hasOwnProperty()
.toString()
Function.prototype
.apply()
.bind()
.call()
.toString()
Array.prototype
.concat()
.filter()
.forEach()
.join()
.map()
.pop()
.push()
.shift()
...
String.prototype
.charAt()
.match()
.replace()
.split()
.slice()
.substr()
.toUpperCase()
.toLowerCase()
...
.constructor()
.arguments
.length
.name
.__proto__
.constructor()
.length
.__proto__
.constructor()
.length
.__proto__
Object.prototype
.hasOwnProperty()
.toString()
Function.prototype
.apply()
.bind()
.call()
.toString()
Array.prototype
.concat()
.filter()
.forEach()
.join()
.map()
.pop()
.push()
.shift()
...
.constructor()
.arguments
.length
.name
.__proto__
.constructor()
.length
.__proto__
Object.prototype
.hasOwnProperty()
.toString()
Function.prototype
.apply()
.bind()
Array.prototype
.forEach()
.push()
Object.prototype
.hasOwnProperty()
.toString()
Function.prototype
.apply()
.bind()
Array.prototype
.forEach()
.push()
Array
.arguments
.length
myArr
[0]
[1]
.length
var myArr = new Array('a', 'b');
var myArr = ['a', 'b'];
is equivalent to
.prototype
.constructor
Object.prototype
.hasOwnProperty()
.toString()
Array.prototype
.forEach()
.push()
myArr
[0]
[1]
.length
var myArr = ['a', 'b'];
Object.prototype
.hasOwnProperty()
.toString()
Array.prototype
.forEach()
.push()
myArr
[0]
[1]
.length
Object.prototype
.hasOwnProperty()
.toString()
Array.prototype
.forEach()
.push()
myArr
[0]
[1]
.length
Object.prototype
.hasOwnProperty()
.toString()
Array.prototype
.forEach()
.push()
myArr
[0]
[1]
.length
Object.prototype
.hasOwnProperty()
.toString()
Function.prototype
.apply()
.bind()
.call()
.toString()
Array.prototype
.concat()
.filter()
.forEach()
.join()
.map()
.pop()
.push()
.shift()
...
String.prototype
.charAt()
.match()
.replace()
.split()
.slice()
.substr()
.toUpperCase()
.toLowerCase()
...
.constructor()
.arguments
.length
.name
.__proto__
.constructor()
.length
.__proto__
.constructor()
.length
.__proto__
Object.prototype
.hasOwnProperty()
.toString()
Function.prototype
.apply()
.bind()
.call()
.toString()
.constructor()
.arguments
.length
.name
.__proto__
Object.prototype
.hasOwnProperty()
.toString()
Function.prototype
.apply()
.bind()
Function
.arguments
.caller
.length
.name
Object
.create()
.keys()
...
.__proto__
.prototype
.name
...
.__proto__
.prototype
Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.prototype
Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
( except Object.create(null) )
Object.prototype.constructor === Object // true
Function.prototype.constructor === Function // true
Function.constructor.prototype ===
Function.prototype
Inheritance (classical)
Object.prototype
.hasOwnProperty()
.toString()
Animal
.arguments
.name
Animal.prototype
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
Function
.arguments
.name
function Animal() {}
var Animal = function () {};
var Animal = new Function();
is roughly equivalent to
is roughly equivalent to
// Animal.name === "Animal"
// Animal.name === ""
// Animal.name === "anonymous"
Object.prototype
.hasOwnProperty()
.toString()
Animal
.arguments
.name
Animal.prototype
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
Function
.arguments
.name
function Animal() {}
Animal.prototype.poop = function () {};
.poop()
Object.prototype
.hasOwnProperty()
.toString()
Animal
.arguments
.name
Animal.prototype
.poop()
Dog
.arguments
.name
Dog.prototype
.bark()
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
Function
.arguments
.name
function Dog() {}
Object.prototype
.hasOwnProperty()
.toString()
Animal
.arguments
.name
Animal.prototype
.poop()
Dog
.arguments
.name
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function () {};
function Dog() {
Animal.call(this);
}
Function
.arguments
.name
function Dog() {}
Dog.prototype
.bark()
Object.prototype
.hasOwnProperty()
.toString()
Animal
.arguments
.name
Animal.prototype
.poop()
Dog
.arguments
.name
Dog.prototype
.bark()
fido
build data object
lassie
build data object
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
Function
.arguments
.name
var fido = new Dog();
var lassie = new Dog():
function Animal() {...}
Animal.prototype.poop = function () {...};
function Dog() {
Animal.call(this);
};
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function () {...};
var fido = new Dog(...);
var lassie = new Dog(...);
Object.create()
ES5 (2009)
class, extends
ES6 (2015)
Simple
Easy
an empty object
link up the prototype chain
to the constructor function
if constructor function returns undefined
an empty object
link up the prototype chain
to the constructor function
if constructor function returns undefined
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Animal
.arguments
.name
Animal.prototype
.poop()
Dog
.arguments
.name
Dog.prototype
.bark()
fido
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
var fido = new Dog();
fido
Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Animal
.arguments
.name
Animal.prototype
.poop()
Dog
.arguments
.name
Dog.prototype
.bark()
fido
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Animal
.arguments
.name
Animal
.poop()
Dog
.arguments
.name
Dog
.bark()
fido
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Animal
.arguments
.name
animal
.poop()
Dog
.arguments
.name
dog
.bark()
fido
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
Step 3: Use standard camelCase
Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Animal
.arguments
.name
animal
.poop()
Dog
.arguments
.name
dog
.bark()
fido
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
Step 3: Use standard camelCase
Step 4: Only use plain objects
Object.prototype
.hasOwnProperty()
.toString()
animal
.poop()
dog
.bark()
fido
var fido = Object.create(dog);
Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Animal
.arguments
.name
Animal.prototype
.poop()
Dog
.arguments
.name
Dog.prototype
.bark()
fido
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
Parent
prototype
Child
prototype
Typed
Instance
Parent
"class"
Child
"class"
Object.prototype
.hasOwnProperty()
.toString()
animal
.poop()
dog
.bark()
fido
object
object
object
var animal = {
poop: function () {...}
};
var dog = _.create(animal, {
bark: function () {...}
};
var fido = _.create(dog);
var lassie = _.create(dog);
function Animal() {...}
Animal.prototype.poop = function () {...};
function Dog() {
Animal.call(this);
};
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function () {...};
var fido = new Dog(...);
var lassie = new Dog(...);
function Animal() {...}
Animal.prototype.poop = function () {...};
function Dog() {
Animal.call(this);
};
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function () {...};
var fido = new Dog(...);
var lassie = new Dog(...);
class Animal {
poop() {...}
}
class Dog extends Animal {
bark() {...}
}
var fido = new Dog();
var lassie = new Dog();
Object.create()
ES5 (2009)
class, extends
ES6 (2015)
class Animal {
poop() {...}
}
class Dog extends Animal {
bark() {...}
}
var fido = new Dog();
var lassie = new Dog();
var animal = {
poop() {...}
};
var dog = _.create(animal, {
bark() {...}
};
var fido = _.create(dog);
var lassie = _.create(dog);
var fido = Object.create(dog);
var fido = new Dog;
2.3 microseconds to create 1 dog
0.23 seconds to create 100,000 dogs
1.6 microseconds to create 1 dog
0.16 seconds to create 100,000 dogs
Factory functions & performance
if (fido instanceof Dog) {
doSomething();
}
if (fido.bark) {
doSomething();
}
if (fido.constructor === Dog) {
doSomething();
}
if (fido.isDog) {
doSomething();
}
Simple
Easy
Object Relation
class, extends & new
Object.create()
Object Creation
class & new
Object Literals
-- Gang of Four
Murder Robot Dog Dilemma
Object.prototype
.hasOwnProperty()
.toString()
Animal.prototype
.poop()
Dog.prototype
.bark()
fido
animal
.poop()
dog
.bark()
fido
animal
.poop()
dog
.bark()
fido
.poop()
.bark()
Object.prototype
.hasOwnProperty()
.toString()
function animal() {
return {
eat: function () {...},
poop: function () {...}
};
}
function animal() {
return {
eat: function () {...},
poop: function () {...}
};
}
function animal(isCarnivore) {
return {
isCarnivore: isCarnivore,
eat: function () {...},
poop: function () {...}
};
}
function animal(isCarnivore) {
return {
isCarnivore: isCarnivore,
eat: function () {...},
poop: function () {...}
};
}
function animal(isCarnivore) {
var privateVariable1 = ...,
privateVariable2 = ...;
return {
isCarnivore: isCarnivore,
eat: function () {...},
poop: function () {...}
};
}
function animal(isCarnivore) {
var privateVariable1 = ...,
privateVariable2 = ...;
return {
isCarnivore: isCarnivore,
eat: function () {...},
poop: function () {...}
};
function privateFunction1() {...}
function privateFunction2() {...}
}
function animal(isCarnivore) {
var privateVariable1 = ...,
privateVariable2 = ...;
return {
isCarnivore: isCarnivore,
eat: function () {...},
poop: function () {...}
};
function privateFunction1() {...}
function privateFunction2() {...}
}
function animal() {
return {
eat: function () {...},
poop: function () {...}
};
}
function dog() {
return {
bark: function () {...},
howl: function () {...}
};
}
var fido = Object.assign({}, animal(), dog());
Object Relation
class, extends & new
Object.create()
Object.assign()
Object Creation
class & new
Object Literals
Factory Functions
Object.prototype
.hasOwnProperty()
.toString()
Function
.arguments
.name
Animal
.arguments
.name
Animal.prototype
.poop()
Dog
.arguments
.name
Dog.prototype
.bark()
fido
build data object
lassie
build data object
Object
.create()
.keys()
Function.prototype
.call()
.apply()
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
.prototype
.constructor
-- Seneca the Younger (4 BC - 65 AD)
Modern derivation