Parlez-Vous JavaScript

52c6174ba60557536f93809b4e95d97c?s=47 Angus Croll
November 30, 2012

Parlez-Vous JavaScript

You can spot the tourists a mile away. In Singapore they’re the ones drinking slings at the Raffle’s Long Bar; in JavaScript they’re the ones stuffing their favourite paradigms into a language that never needed them and works better without them.

In this talk, your humble tour guide will wander the back alleys of JavaScript in search of native patterns, uncovering the idioms that work with the language instead of fighting it. We’ll visit some fabulous local haunts: mixins, functional expressions, context injection and of course closures, while trying not to make fun of the garish tourist traps (classes, are you listening?)

52c6174ba60557536f93809b4e95d97c?s=128

Angus Croll

November 30, 2012
Tweet

Transcript

  1. Parlez-vous JavaScript? @angustweets

  2. None
  3. I work at Twitter. We work with JavaScript. Not against

    it.
  4. “The grain tells you which way the wood wants to

    be cut” Charles Miller fishbowl.pastiche.org
  5. Episode 1 The Accidental Tourist

  6. The Problem

  7. (weird shit) JAVA!! But Easier!! (Deceptively Familiar Syntax) (weird shit)

    WTF?
  8. JavaScript Ruby Python Java Shell PHP C C++ 21% 13%

    8% 8% 8% 7% 6% 4% github.com/languages
  9. If languages were vacation destinations, JavaScript would be Paris

  10. How not to pack for JavaScript

  11. C++ RUBY JavaScript To:

  12. JavaScript To: strong typing static ‘this’ second class functions OOP

  13. Episode 2 Do as the Locals Do...

  14. The Five Hills of JavaScript...

  15. closures first-class functions dynamic ‘this’ prototypes call/apply

  16. Episode 3 OOP not spoken here

  17. OK, I lied Constructor-Prototype chaining* is OOP *having one custom

    prototype extend another
  18. But it’s awkward and unnatural...

  19. 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();
  20. Object.create liberates prototype chaining from constructors.

  21. var animalProto = { speak: function() { console.log(this.says); } }

    var walkingAnimalProto = Object.create( animalProto, { walk: { value: function() { console.log('walking'); } } //... } );
  22. ES 6 is giving us class. Some libraries have there

    own versions.
  23. //Prototype.js var SwimmingAnimal = Class.create(Animal, { type: 'SwimmingAnimal', speak: function($super)

    { return $super() + ", glug"; } }); //Dustin Diaz's "klass" var Alien = SuperHuman.extend({ beam: function() { this.supr(); // beam into space } });
  24. Do you even want classes?

  25. Animal Walking Animal Swimming Animal Flying Animal Cat Elephant Crocodile

    Whale Eagle Bat Egg-laying Animal Migrating Animal
  26. Animal Walking Animal Swimming Animal Flying Animal Cat Elephant Crocodile

    Whale Eagle Bat Egg-laying Animal Migrating Animal WTF? I walk too!!
  27. Migrating Animal Egg-laying Animal Flying Animal Swimming Animal Walking Animal

    Duck? Animal Cat Elephant Crocodile Whale Eagle Bat
  28. This hierarchy monster is not fussy es6 class Object.create class

    framework new Constructor
  29. However.

  30. The sad thing is that anyone even cares about inheritance

    hierarchies... Because in JavaScript they’re quite unnecessary...
  31. Episode 4 JavaScript Mixins

  32. Property Copy Mixins...

  33. var withWalking = { walk: function() { console.log('walking'); }, turn:

    function(direction) { console.log('turning', direction); }, stopWalking: function() { console.log('stopped walking'); } };
  34. 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);
  35. Functional Mixins...

  36. var withWalking = function() { this.walk = function() { console.log('walking');

    }; this.turn = function(direction) { console.log('turning', direction); }; this.stopWalking = function() { console.log('stopped walking'); }; };
  37. function Crocodile(name, gender) { this.name = name; this.gender = gender;

    }; Crocodile.prototype.stalkTourists = function() { //.. }; withWalking.call(Crocodile.prototype); withSwimming.call(Crocodile.prototype);
  38. Episode 5 Monkey Patching: The Good Parts

  39. https://twitter.com/rockstar_/status/147367323488108544

  40. Q. How do you patch a 3rd party library without

    touching it?
  41. A. Wrap it.

  42. // Using underscore _.each = _.wrap(_.each, function(each, collection, fn, context)

    { each(collection, fn, context); return collection; } ); _.each([1,2,3], alert); //[1,2,3]
  43. Also, why are you still using underscore when there’s...

  44. github.com/kriskowal/es5-shim

  45. Episode 6 Functional

  46. High Order Functions

  47. var fruit = ["grape ", "pear ", "apple"]; var result

    = []; for (var i = 0; i < fruit.length; i++) { result.push(fruit[i].trim()); } result; //["grape", "pear", "apple"]
  48. fruit.map(function(each) { return each.trim(); });

  49. function globalize(methodName) { return function(obj) { return obj[methodName](); } }

  50. fruit.map(function(each) { return each.trim(); });

  51. fruit.map(globalize('trim'));

  52. Currying* (partial application) *yes I know it’s not technically currying

  53. add curry 7 .curry(7) var add7= add7(5); //12 add(x,y) 5

    7
  54. Function.prototype.curry = function() { if (arguments.length < 1) { //nothing

    to curry with - return function return this; } var method = this; var args = [].slice.call(arguments); return function() { return method.apply( this, args.concat([].slice.call(arguments))); } }
  55. Function Composition

  56. Math.pow alert

  57. alert( ) Math.pow Math.pow var alertPower = alert.compose(Math.pow);

  58. Function.prototype.compose = function(argFunction) { var invokingFunction = this; return function()

    { return invokingFunction.call( this,argFunction.apply(this,arguments)); } }
  59. Currying + Composition =

  60. var sliceToRegEx = ''.slice.curry(0).compose(''.search); var parseAlpha = sliceToRegEx.curry(/[^ a-zA-Z]/); parseAlpha("fredfrith@gmail.com")

    //"fredfrith"
  61. Episode 7 Beware of imitations...

  62. San Francisco is great etc. But...

  63. San Francisco is great etc. But... its fire hydrants are

    non-standard
  64. EveryOther Fire Dept. wtf.sf?! SFFD X

  65. jQuery is great etc. But...

  66. jQuery is great etc. But... it’s objects are non-standard

  67. //jQuery selectors return jQuery objects var anchors = $('a'); Array.isArray(anchors);

    //false
  68. //jQuery selectors return jQuery objects var anchors = $('a'); Array.isArray(anchors);

    //false anchors.push; //function push() { [native code] } anchors.forEach; //undefined
  69. //jQuery selectors return jQuery objects var anchors = $('a'); Array.isArray(anchors);

    //false anchors.push; //function push() { [native code] } anchors.forEach; //undefined //which means we are stuck in jquery land var hrefs = anchors.map( function(i, elem) {return elem.href} ); !!
  70. //jQuery selectors return jQuery objects var anchors = $('a'); Array.isArray(anchors);

    //false anchors.push; //function push() { [native code] } anchors.forEach; //undefined //which means we are stuck in jquery land var hrefs = anchors.map( function(i, elem) {return elem.href} ); //perpetually Array.isArray(hrefs); //false ;-( !!
  71. Unless you do this...

  72. var anchors = $('a'); Array.isArray(anchors); //false hrefs = [].map.call(anchors, function(elem)

    {return elem.href} ); Array.isArray(hrefs); //true :)
  73. or this...

  74. var anchors = $('a'); Array.isArray(anchors); //false var anchors = [].slice.call(anchors);

    Array.isArray(anchors); //true
  75. Episode 8 Everyday JavaScript

  76. you could do this...

  77. function getEventTarget(evt) { if (!evt) { evt = window.event; }

    if (!evt) { return; } var target; if (evt.target) { target = evt.target; } else { target = evt.srcElement; } return target; }
  78. or you could do this...

  79. function getEventTarget(evt) { evt = evt || window.event; return evt

    && (evt.target || evt.srcElement); }
  80. Episode 9 Too long; fell asleep?

  81. “Every language has its own way. Follow its form. Don’t

    try to program as if you were using another language.” Marijn Haverbeke Eloquent JavaScript
  82. Questions? @angustweets speakerdeck.com/anguscroll/parlez-vous-javascript