Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Parlez-Vous JavaScript

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?)

Angus Croll

November 30, 2012
Tweet

More Decks by Angus Croll

Other Decks in Technology

Transcript

  1. Parlez-vous
    JavaScript?
    @angustweets

    View full-size slide

  2. I work at Twitter.
    We work with JavaScript.
    Not against it.

    View full-size slide

  3. “The grain tells you which way
    the wood wants to be cut”
    Charles Miller
    fishbowl.pastiche.org

    View full-size slide

  4. Episode 1
    The Accidental Tourist

    View full-size slide

  5. (weird shit)
    JAVA!!
    But Easier!!
    (Deceptively
    Familiar Syntax)
    (weird shit)
    WTF?

    View full-size slide

  6. JavaScript
    Ruby
    Python
    Java
    Shell
    PHP
    C
    C++
    21%
    13%
    8%
    8%
    8%
    7%
    6%
    4%
    github.com/languages

    View full-size slide

  7. If languages were vacation destinations,
    JavaScript would be Paris

    View full-size slide

  8. How not to pack for JavaScript

    View full-size slide

  9. C++
    RUBY
    JavaScript
    To:

    View full-size slide

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

    View full-size slide

  11. Episode 2
    Do as the Locals Do...

    View full-size slide

  12. The Five Hills of JavaScript...

    View full-size slide

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

    View full-size slide

  14. Episode 3
    OOP not spoken here

    View full-size slide

  15. OK, I lied
    Constructor-Prototype chaining* is
    OOP
    *having one custom prototype extend another

    View full-size slide

  16. But it’s awkward and unnatural...

    View full-size slide

  17. 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();

    View full-size slide

  18. Object.create liberates prototype
    chaining from constructors.

    View full-size slide

  19. var animalProto = {
    speak: function() {
    console.log(this.says);
    }
    }
    var walkingAnimalProto = Object.create(
    animalProto, {
    walk: {
    value: function() {
    console.log('walking');
    }
    }
    //...
    }
    );

    View full-size slide

  20. ES 6 is giving us class.
    Some libraries have there own versions.

    View full-size slide

  21. //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
    }
    });

    View full-size slide

  22. Do you even want classes?

    View full-size slide

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

    View full-size slide

  24. Animal
    Walking Animal
    Swimming Animal
    Flying Animal
    Cat
    Elephant
    Crocodile
    Whale
    Eagle
    Bat
    Egg-laying Animal
    Migrating Animal
    WTF? I walk
    too!!

    View full-size slide

  25. Migrating Animal
    Egg-laying Animal
    Flying Animal
    Swimming Animal
    Walking Animal
    Duck?
    Animal
    Cat
    Elephant
    Crocodile
    Whale
    Eagle
    Bat

    View full-size slide

  26. This hierarchy monster is not fussy
    es6 class
    Object.create
    class framework
    new Constructor

    View full-size slide

  27. The sad thing is that anyone even cares
    about inheritance hierarchies...
    Because in JavaScript they’re quite
    unnecessary...

    View full-size slide

  28. Episode 4
    JavaScript Mixins

    View full-size slide

  29. Property Copy Mixins...

    View full-size slide

  30. var withWalking = {
    walk: function() {
    console.log('walking');
    },
    turn: function(direction) {
    console.log('turning', direction);
    },
    stopWalking: function() {
    console.log('stopped walking');
    }
    };

    View full-size slide

  31. 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);

    View full-size slide

  32. Functional Mixins...

    View full-size slide

  33. var withWalking = function() {
    this.walk = function() {
    console.log('walking');
    };
    this.turn = function(direction) {
    console.log('turning', direction);
    };
    this.stopWalking = function() {
    console.log('stopped walking');
    };
    };

    View full-size slide

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

    View full-size slide

  35. Episode 5
    Monkey Patching:
    The Good Parts

    View full-size slide

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

    View full-size slide

  37. Q. How do you patch a 3rd party library
    without touching it?

    View full-size slide

  38. // Using underscore
    _.each = _.wrap(_.each,
    function(each, collection, fn, context) {
    each(collection, fn, context);
    return collection;
    }
    );
    _.each([1,2,3], alert); //[1,2,3]

    View full-size slide

  39. Also, why are you still using
    underscore when there’s...

    View full-size slide

  40. github.com/kriskowal/es5-shim

    View full-size slide

  41. Episode 6
    Functional

    View full-size slide

  42. High Order Functions

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  50. 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)));
    }
    }

    View full-size slide

  51. Function Composition

    View full-size slide

  52. Math.pow
    alert

    View full-size slide

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

    View full-size slide

  54. Function.prototype.compose = function(argFunction) {
    var invokingFunction = this;
    return function() {
    return invokingFunction.call(
    this,argFunction.apply(this,arguments));
    }
    }

    View full-size slide

  55. Currying + Composition =

    View full-size slide

  56. var sliceToRegEx = ''.slice.curry(0).compose(''.search);
    var parseAlpha = sliceToRegEx.curry(/[^ a-zA-Z]/);
    parseAlpha("[email protected]") //"fredfrith"

    View full-size slide

  57. Episode 7
    Beware of imitations...

    View full-size slide

  58. San Francisco is great etc. But...

    View full-size slide

  59. San Francisco is great etc. But...
    its fire hydrants are non-standard

    View full-size slide

  60. EveryOther
    Fire Dept.
    wtf.sf?!
    SFFD
    X

    View full-size slide

  61. jQuery is great etc. But...

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  65. //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}
    ); !!

    View full-size slide

  66. //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 ;-(
    !!

    View full-size slide

  67. Unless you do this...

    View full-size slide

  68. var anchors = $('a');
    Array.isArray(anchors); //false
    hrefs = [].map.call(anchors,
    function(elem) {return elem.href}
    );
    Array.isArray(hrefs); //true
    :)

    View full-size slide

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

    View full-size slide

  70. Episode 8
    Everyday JavaScript

    View full-size slide

  71. you could do this...

    View full-size slide

  72. 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;
    }

    View full-size slide

  73. or you could do this...

    View full-size slide

  74. function getEventTarget(evt) {
    evt = evt || window.event;
    return evt && (evt.target || evt.srcElement);
    }

    View full-size slide

  75. Episode 9
    Too long; fell asleep?

    View full-size slide

  76. “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

    View full-size slide

  77. Questions?
    @angustweets
    speakerdeck.com/anguscroll/parlez-vous-javascript

    View full-size slide