Created
April 22, 2019 15:16
-
-
Save deconstructionalism/d5d3c153b375d0998ffdc0f444625194 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ` | |
| OBJECT LITERALS TO MAKE INSTANCES | |
| ` | |
| // this is a model of real world object, a dog | |
| const fido = { | |
| name: 'Fido', | |
| breed: 'Rottweiler', | |
| age: 3, | |
| bark () { | |
| console.log('bork bork') | |
| }, | |
| reciteName () { | |
| console.log(`my name is ${this.name}`) | |
| } | |
| } | |
| const hans = { | |
| name: 'Hans', | |
| breed: 'Shnauser', | |
| age: 1, | |
| bark () { | |
| console.log('bork bork') | |
| }, | |
| reciteName () { | |
| console.log(`my name is ${this.name}`) | |
| } | |
| } | |
| ` | |
| CONSTRUCTOR FUNCTIONS TO MAKE INSTANCES WITHOUT PROTOTYPES | |
| ` | |
| // this is a the actual structure of the model as a function | |
| function Dog (name, age, breed) { | |
| // let this = {} | |
| this.name = name | |
| this.age = age | |
| this.breed = breed | |
| this.bark = function () { | |
| console.log('bork bork') | |
| }, | |
| this.reciteName = function () { | |
| console.log(`my name is ${this.name}`) | |
| } | |
| // return this | |
| } | |
| // problem here is that although the code is more DRY with respect | |
| // to shared properties between dogs, we have the same method repeatedly | |
| // taking up space in each dog | |
| const fido = new Dog('Fido', 3, 'Rottweiler') | |
| const hans = new Dog('Hans', 1, 'Shnauser') | |
| ` | |
| CONSTRUCTOR FUNCTIONS TO MAKE INSTANCES WITHOUT PROTOTYPES | |
| ` | |
| // this is a the actual structure of the model as a function | |
| function Dog (name, age, breed) { | |
| // let this = {} | |
| this.name = name | |
| this.age = age | |
| this.breed = breed | |
| // return this | |
| } | |
| // when you make a constructor function, such as Dog, it is immidietly hooked | |
| // up to a prototype object for it | |
| Dog.prototype.bark = function () { | |
| console.log('bork bork') | |
| } | |
| Dog.prototype.reciteName = function () { | |
| console.log(`my name is ${this.name}`) | |
| } | |
| const fido = new Dog('Fido', 3, 'Rottweiler') | |
| const hans = new Dog('Hans', 1, 'Shnauser') | |
| // > fido.breed | |
| // 'Rottweiler' | |
| // > fido.bark() | |
| // 'bork bork' | |
| // > fido | |
| // { | |
| // name: 'Fido', | |
| // age: 3, | |
| // breed: 'Rottweiler' | |
| // } | |
| // > fido.__proto__ | |
| // Dog.prototype | |
| ` | |
| JS USES SHALLOW INHERITANCE FOR IT'S TYPES | |
| ` | |
| ` | |
| null | |
| | | |
| V | |
| Object | |
| | | |
| V | |
| String, Boolean, Number, [user made object based on constructor] | |
| ` | |
| ` | |
| DEEP INHERTIANCE IN OOP IS AN ANTI-PATTERN! | |
| ` | |
| ` | |
| Object | |
| | | |
| V | |
| Animal -> Reptile -> Iguana | |
| | | |
| V | |
| Mammal | |
| | | | |
| V V | |
| Dog Cat | |
| ` | |
| class Animal { | |
| constructor (numLegs) { | |
| this.numLegs = numLegs | |
| } | |
| breathe () { | |
| console.log('air+1') | |
| } | |
| move () { | |
| console.log(`I'm moving on ${this.numLegs} legs!`) | |
| } | |
| eat () { | |
| console.log('nom nom nom') | |
| } | |
| } | |
| class Mammal extends Animal { | |
| constructor (numLegs) { | |
| super(numLegs) | |
| } | |
| giveMilk () { | |
| console.log('does a body good') | |
| } | |
| gestate () { | |
| console.log('one in the oven') | |
| } | |
| } | |
| class Dog extends Mammal { | |
| constructor (name, age, breed) { | |
| super(4) | |
| this.name = name | |
| this.age = age | |
| this.breed = breed | |
| } | |
| bark () { | |
| console.log('bork bork') | |
| } | |
| reciteName () { | |
| console.log(`my name is ${this.name}`) | |
| } | |
| } | |
| const fido = new Dog('Fido', 3, 'Rottweiler') | |
| // > fido.bark() | |
| // 'bork bork' | |
| // > fido.breathe() | |
| // 'air+1' | |
| // this all looks good until we need to accomodate a RobotDog... | |
| ` | |
| ENTER ROBOTDOG | |
| ` | |
| ` | |
| Object | |
| | | |
| V | |
| Robot | |
| | | |
| V | |
| RobotDog < - Dog | |
| ` | |
| const aibo = new RobotDog('aibo', 'kill all humans') | |
| // > aibo.catchPhrase() | |
| // 'kill all humans' | |
| // this is a problem! | |
| // > aibo.breathe() | |
| // 'air+1' | |
| ` | |
| USE COMPOSITION INSTEAD OF INHERITANCE WHEN YOU CAN | |
| ` | |
| const breathe = function () { | |
| console.log('air+1') | |
| } | |
| const eat = function () { | |
| console.log('nom nom nom') | |
| } | |
| const reciteCatchPhrase = function () { | |
| console.log(this.catchPhrase) | |
| } | |
| const bark = function () { | |
| console.log('bork bork') | |
| } | |
| const reciteName = function () { | |
| console.log(`my name is ${this.name}`) | |
| } | |
| const killAllHumans = function () { | |
| console.log('on it buddy') | |
| } | |
| const dog = function (name, breed, age) { | |
| const methods = { | |
| breathe, | |
| eat, | |
| reciteName, | |
| bark | |
| } | |
| return { | |
| name, | |
| breed, | |
| age, | |
| ...methods | |
| } | |
| } | |
| const robotDog = function (name, catchPhrase) { | |
| const methods = { | |
| killAllHumans, | |
| reciteCatchPhrase, | |
| bark | |
| } | |
| return { | |
| name, | |
| catchPhrase, | |
| age, | |
| ...methods | |
| } | |
| } | |
| ` | |
| LINKS | |
| https://medium.com/humans-create-software/composition-over-inheritance-cb6f88070205 | |
| https://medium.com/code-monkey/object-composition-in-javascript-2f9b9077b5e6 | |
| https://medium.com/@TK_CodeBear/inheritance-vs-object-composition-4723c1902b28 | |
| https://medium.com/javascript-scene/composing-software-an-introduction-27b72500d6ea | |
| ` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment