Contemporary
JavaScript

Questions to answer

  • What JS framework should I use?
  • How can I write a maintainable JS app?

What language is this?

import {ASSIGNED, ACTIVE} from '../../Domain/Inspections/InspectionState'

export default class InspectionsApi {
    
    constructor(api, inspectionMapper) {
        this.api = api;
        this.inspectionMapper = inspectionMapper;
    }

    async retrieve() {
        var raw = await this.api.get('inspections', {
            query: {
                clerk_id: 'me',
                state_id: [ASSIGNED, ACTIVE]
            }
        });
   
        return raw.body.map(insp => this.inspectionMapper.fromApi(insp));
    }

}

Web programming

function switchEntries() {
    if (document.all) {
        document.election.presidents.item(0).text = 'Bill Clinton';
    }
    else if (document.layers) {
        document.election.presidents[0].text = 'Bill Clinton';
    }
    else if (document.getElementById) {
        document.election.leaving.text = 'Bill Clinton';
    }
}
<FORM NAME="election">
    <SELECT NAME="presidents">
        <OPTION NAME="leaving">Al Gore
        <OPTION SELECTED>George W. Bush
    </SELECT>
    <INPUT TYPE="button" VALUE="Switch first option"
      onclick="switchEntries()">
</FORM>

Web programming (2)

$('input[type="button"]').click(function() {
    $('option:first').text('Bill Clinton');
});
<form>
    <select>
        <option>Al Gore</option>
        <option selected>George W. Bush</option>
    </select>
    <input type="button" value="Switch first option" />
</form>

Web programming (3)

  • Single Page Applications (SPA's)
  • Require modular design
  • Separation of concerns
  • Typically MVC

Frameworks provide
MVC boilerplate

  • BackboneJS
  • AngularJS
  • EmberJS
  • Probably 1000's more...

Lots of frameworks!

  • Encapsulation
  • Dependency mgmt
  • Packaging

Encapsulation

(function() {
    var myVar = ...;
    // your code here...

})();

Dependencies

(function($, undefined) {

    // $ bound to dependency jQuery

    $.doSomething();

    // undefined is actually undefined

})(jQuery);

AMD

define(['jquery'] , function ($) {
    function add(a, b) {
        return a + b;
    }

    return add;
});

adder.js

define(['adder', 'jquery'] , function(adder, $) {
    adder(3, 4); // 7
});

main.js

Need a module loader

  • Typically require.js
  • Takes a config file describing dependencies
  • Makes sure deps are loaded
  • Passes deps to modules
  • Builder available to combine app + all deps

Meanwhile on the server...

  • Node.js ecosystem very large
  • Uses common.js module definition
var $ = require('jquery');

function add(a, b) {
    return a + b;
}

module.exports = add;

Commonjs modules

  • Very large collection of packages available
  • Hard to load asynchronously
  • Can combine into browser module using browserify
  • Usually automatic rebuilding during development
    with watchify

Package distribution

  • Browser modules are distributed with bower
    • "bower install" installs deps from bower.json
  • Node.js modules are distributed with npm
    • "npm install" installs deps from package.json

Automating tasks

  • Downloading dependencies
  • Building distribution files (js, css, etc.)
  • Running tests
  • Auto-reloading browsers

Grunt

  • Like "make" but with colors
  • Targets configured in Gruntfile.js

Gulp

  • Like "grunt" but with more colors
  • Targets configured in gulpfile.js
  • Streams output from one tool to another

Testing frameworks

  • JasmineJS
  • Mocha
  • QUnit
  • Probably a lot more...

Trends in JS

  • Compiling to JS
  • JS language evolving (ES5, ES6)
  • Handling asynchronous code
  • Virtual DOM

Compiling to JS

  • Coffeescript: lean syntax for JS
square = (x) -> x * x

math =
  root:   Math.sqrt
  square: square
  cube:   (x) -> x * square x

cubes = (math.cube num for num in list)
var square = function(x) {
  return x * x;
};

var math = {
  root: Math.sqrt,
  square: square,
  cube: function(x) {
    return x * square(x);
  }
};

var cubes = (function() {
  var i, len, results;
  results = [];
  for (i = 0, len = list.length; i < len; i++) {
    num = list[i];
    results.push(math.cube(num));
  }
  return results;
})();

Compiling to JS (2)

  • TypeScript
  • Dart
  • ClojureScript
  • Emscripten - LLVM to asm.js

Evolving JavaScript - ES5

"use strict";

// Accessors
var x = { get foo() { return 'abc'; } }

// Functional programming
[1, 2, 3, 4].filter(function(x) { return x % 2 === 0; })
            .map(function(x) { return x * x; })
            .forEach(function(x) { console.log(x); });
  • Already available in modern browsers
  • Use es5-shim for polyfills

Evolving JavaScript - ES6

import {ASSIGNED, ACTIVE} from '../../Domain/Inspections/InspectionState'

export default class InspectionsApi {
    
    constructor(api, inspectionMapper) {
        this.api = api;
        this.inspectionMapper = inspectionMapper;
    }

    async retrieve() {
        var raw = await this.api.get('inspections', {
            query: {
                clerk_id: 'me',
                state_id: [ASSIGNED, ACTIVE]
            }
        });
   
        return raw.body.map(insp => this.inspectionMapper.fromApi(insp));
    }

}
  • Use Google Traceur to compile to JS

Trends in JS

  • MVC: two-way-binding
    • Models are bound to controls
    • When model change -> update control
    • When control changes -> update model
  • Hard to debug
  • Solution: one-way data flow

Facebook React

var HelloMessage = React.createClass({
  render: function() {
    return <div>Hello {this.props.name}</div>;
  }
});

React.render(<HelloMessage name="John" />, mountNode);
Made with Slides.com