Slide 1

Slide 1 text

How We Learned To Stop Worrying And Love JavaScript @danwrong @angustweets

Slide 2

Slide 2 text

We’ve been busy...

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Rethinking twitter.com ‣ Use the right tool for the job. Don’t JavaScript all the things. ‣ Take advantage of the browser and of the nature of JavaScript rather than fighting it.

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Reuse patterns that make use of JavaScript rather than fight it

Slide 7

Slide 7 text

The hardest part...

Slide 8

Slide 8 text

The hardest part...

Slide 9

Slide 9 text

The hardest part...

Slide 10

Slide 10 text

So, talking animals it is... meow!!

Slide 11

Slide 11 text

Prototypes ‣ JavaScript’s Agent of Re-use ‣ Flexible but Awkward ‣ new syntax encourages classical model ‣ Prototype chains are single rooted ‣ Inheritance syntax is gnarly

Slide 12

Slide 12 text

var Animal = function(gender, says) { this.gender = gender; this.says = says; }; var WalkingAnimal = function(gender, says) { Animal.call(this, gender, says); } WalkingAnimal.prototype = new Animal(); // http://jsfiddle.net/96BSq/

Slide 13

Slide 13 text

var Animal = function(gender, says) { this.gender = gender; this.says = says; }; var WalkingAnimal = function(gender, says) { Animal.call(this, gender, says); } WalkingAnimal.prototype = new Animal(); // http://jsfiddle.net/96BSq/

Slide 14

Slide 14 text

Class syntax ‣ JS native class syntax scheduled for ES6 ‣ class, extend and super are reserved words ‣ Library implementation varies widely and abstraction is often leaky (‘const’, ‘static’) ‣ In particular, the relationship between this and super is difficult

Slide 15

Slide 15 text

//Prototype.js var SwimmingAnimal = Class.create(Animal, { type: 'SwimmingAnimal', speak: function($super) { return $super() + ", glug"; } }); //Dustin Diaz's "klass" var Alien = SuperHuman.extend({ beem: function() { this.supr(); // beem into space } });

Slide 16

Slide 16 text

//Prototype.js var SwimmingAnimal = Class.create(Animal, { type: 'SwimmingAnimal', speak: function($super) { return $super() + ", glug"; } }); //Dustin Diaz's "klass" var Alien = SuperHuman.extend({ beem: function() { this.supr(); // beem into space } });

Slide 17

Slide 17 text

//Prototype.js var SwimmingAnimal = Class.create(Animal, { type: 'SwimmingAnimal', speak: function($super) { return $super() + ", glug"; } }); //Dustin Diaz's "klass" var Alien = SuperHuman.extend({ beem: function() { this.supr(); // beem into space } });

Slide 18

Slide 18 text

Class hierarchies

Slide 19

Slide 19 text

Class hierarchies WTF? I walk too!

Slide 20

Slide 20 text

Class hierarchies Duck? WTF? I walk too!

Slide 21

Slide 21 text

Class hierarchies Duck? WTF? I walk too!

Slide 22

Slide 22 text

Classical inheritance ‣ Requires up-front knowledge of general case ‣ Single rooted hierarchy ‣ Types are often too generalized to map to real life coding problems (some animals swim AND walk)

Slide 23

Slide 23 text

Beyond classification ‣ 19th century British philosophers Whewell and Jevons argued that there are no objectively “right” classifications ‣ “In general, when working with prototypes, one typically chooses not to categorize but to exploit alikeness.” Antero Taivalsaari (Nokia Research Center) - Journal of Object Oriented Programming Nov/Dec 1997

Slide 24

Slide 24 text

Mixins ‣ JavaScript has first class functions ‣ Any property can be assigned to any object

Slide 25

Slide 25 text

//A property copy mixin var withWalking = { walk: function() { console.log('walking'); }, turn: function(direction) { console.log('turning', direction); }, stopWalking: function() { console.log('stopped walking'); } };

Slide 26

Slide 26 text

var extend = function(destination, source) { for (var k in source) { if (source.hasOwnProperty(k)) { destination[k] = source[k]; } } return destination; }; extend(Crocodile.prototype, withWalking); extend(Crocodile.prototype, withSwimming); //http://jsfiddle.net/29tW5/

Slide 27

Slide 27 text

Property copy mixins ‣ No hierarchical constraints ‣ Functionality is grouped by what it does not who it belongs to ‣ BUT... ‣ Mixin has no reference to target properties ‣ Properties can only clobber ‣ Target object requires intimate knowledge of mixin properties

Slide 28

Slide 28 text

Functional mixins ‣ Mixins are functions that assign properties to the ‘this’ object. ‣ Mixins are directly invoked in the context of the target object by means of call/apply

Slide 29

Slide 29 text

var withWalking = function() { this.walk = function() { console.log('walking'); }; this.turn = function(direction) { console.log('turning', direction); }; this.stopWalking = function() { console.log('stopped walking'); }; }; //http://jsfiddle.net/uyZZL/13/

Slide 30

Slide 30 text

function Crocodile(name, gender) { this.name = name; this.gender = gender; }; Crocodile.prototype.stalkTourists = function() { //.. }; withWalking.call(Crocodile.prototype); withSwimming.call(Crocodile.prototype);

Slide 31

Slide 31 text

Advice: before, after and around ‣ A mixin that adds, underscore.js style, before(), after() and around() to an object. ‣ Other mixins can use this to augment existing methods.

Slide 32

Slide 32 text

withAdvice.call(Crocodile.prototype); function withFlu() { this.before(“walk”, function() { console.log('sniff'); }) } var sickCrocodile = new Crocodile(); withFlu.call(sickCrocodile); sickCrocodile.walk(); //"sniff, pad, pad, pad, pad"

Slide 33

Slide 33 text

function withCharacterCounter() { this.updateCounter = function() { //... }; //add advice after core initialize method this.after('initialize', function() { this.$counter = this.select('counter'); this.on('uiTextUpdated', this.updateCounter); }); }

Slide 34

Slide 34 text

Functional mixins ‣ Mixins as verbs instead of nouns. ‣ Mixins are functions. We can take advantage of closure scope, arguments and context. ‣ A mixin can be applied to any object type: prototype, instance, whatever. ‣ Advice allows functional mixins to augment existing functions, not clobber them. ‣ Works with the language, simple to understand, no surprises. Debuggable.

Slide 35

Slide 35 text

Putting it to work...

Slide 36

Slide 36 text

function Storage() { this.initialize.call(this, arguments); } function baseStorage() { this.initialize = function(namespace) { this.namespace = namespace } this.encode = function(item) { return JSON.stringify(item) } this.decode = function(item) { return JSON.parse(item) } if (window.localStorage) { localStorageEngine.call(this); return; } if (document.documentElement.addBehavior) { userDataEngine.call(this); return; } memoryStorageEngine.call(this); } withAdvice.call(Storage.prototype); baseStorage.call(Storage.prototype);

Slide 37

Slide 37 text

function localStorageEngine() { this.getItem = function(key) { return this.decode(localStorage.getItem(this.namespace + key)); } this.setItem = function(key, val) { return localStorage.setItem(this.namespace + key, this.encode(val)); } }

Slide 38

Slide 38 text

function memoryStorageEngine() { var store = {}; this.after('initialize', function() { this.store = store[this.namespace] = store[this.namespace] || {}; }); this.getItem = function(key) { return this.decode(this.store[this.namespace + key]); } this.setItem = function(key, val) { return this.store[this.namespace + key] = this.encode(val); } }

Slide 39

Slide 39 text

function withEncryption() { this.after('initialize', function(namespace, secret) { this.secret = secret; }); this.around('decode', function(decode, val) { return decode(aes.dec(val, this.secret)); }) this.around('encode', function(encode, val) { return aes.enc(encode(val), this.secret); }); } var encryptedStorage = new Storage('secretStuff'); withEncryption.call(encryptedStorage);

Slide 40

Slide 40 text

Overview ‣ Functional mixins and advice/AOP are the shit ‣ Make use of JavaScript’s biggest strength - functions ‣ Extremely simple ‣ Endless flexibility ‣ Drop your class implementations and use this stuff now

Slide 41

Slide 41 text

Questions?

Slide 42

Slide 42 text

@jointheflock Visit the booth and chat to us twitter.com/jobs Happy hour tonight Beer.js!