JavaScript Growing Up
 Modules, Platform Consistency and Harmony




              David Padbury
Between HTML5 and Node, JavaScript
is seeing a staggering level of adoption.
The patterns and tools and practices that will form
 the foundation of Modern JavaScript are going to
have to come from outside implementations of the
                  language itself
                                       - Rebecca Murphey
Modules
Java has import


C# has using


 JavaScript has?
    Nothing.
So JavaScript authors used what we had in
the language to provide what we needed.
But before we get to that,
 first some prerequisites.
Everything is global


// lib1.js
var name = 'Barry';

function sayHi() {
    alert("Hi, I'm " + name);
}

<script src="lib1.js"></script>
<script>
    something();
    console.log(name); // Barry
</script>
Which could make including multiple libraries challenging

         // lib1.js
         function something() {
             console.log('foo');
         }

         // lib2.js
         function something() {
             console.log('bar');
         }

         <script src="lib1.js"></script>
         <script src="lib2.js"></script>
         <script>
             something();
         </script>
Using simple JavaScript constructs we can emulate many
          traditional organization techniques

     ;(function(lib1) {

          lib1.something = function() {
              ...
          };

     })(window.lib1 = window.lib1 || {});

     lib1.something();
     lib2.something();
function namespace(ns) {
    var obj = window;

    ns.split('.').forEach(function(component) {
        obj = typeof obj[component] !== 'undefined'
            ? obj[component]
            : obj[component] = {};
    });

    return obj;
}
(function(data) {
    data.something = function() {
        ...
    };
})(namespace('lab49.app.data'));
(function(example) {

   function privateAdd(num1, num2) {
       return num1 + num2;
   }

   example.add = function(num1, num2) {
       return privateAdd(num1, num2);
   };

})(namespace('lab49.example'));



console.log(typeof example.add); // function
console.log(typeof example.privateAdd); // undefined
console.log(typeof privateAdd); // undefined
Server-side JavaScript authors started to talk about
what a more robust module system would look like.
I generally support the CommonJS idea, but let’s
be clear: it’s hardly a specification handed down by
the gods (like ES5); it’s just some people discussing
  ideas on a mailing list. Most of these ideas are
          without actual implementations.
                                   - Ryan Dahl (creator of node.js)
Introduced a simple API for dealing with modules.

       require for importing a module.

  exports for exposing stuff from a module.




             http://wiki.commonjs.org/wiki/Modules/1.1.1
// math.js
exports.add = function() {
    var sum = 0, i = 0, args = arguments, l = args.length;
    while (i < l) {
        sum += args[i++];
    }
    return sum;
};

//increment.js
var add = require('math').add;
exports.increment = function(val) {
    return add(val, 1);
};

// program.js
var inc = require('increment').increment;
var a = 1;
inc(a); // 2
CommonJS modules are now the de-facto
    for server based JavaScript.
var http = require('http');

var server = http.createServer(function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hi Lab!');
});
There are now a number of tools to bring
  CommonJS modules to the browser.

         https://github.com/substack/node-browserify


             https://github.com/sstephenson/stitch
var stitch = require('stitch');
var express = require('express');

var package = stitch.createPackage({
  paths: [__dirname + '/lib', __dirname + '/vendor']
});

var app = express.createServer();
app.get('/application.js', package.createServer());
app.listen(3000);
There are some problems with using this
    module format in the browser.
Asynchronous Module Definition
  (Commonly known as AMD)




    https://github.com/amdjs/amdjs-api/wiki/AMD
define for creating a module definition.
define('personView', ['models/person'], function(person) {
    return {
        initialize: function() {
            ...
        }
    };
});
AMD is now used by RequireJS, Dojo and even Node.
RequireJS also supports text templates.
Becoming the most common way to structure large JavaScript
    applications, both on the server and in the browser.
JS.next will be introducing language level modules.
These are similar to the modules we’ve been looking at.
module Math {
    export function add(x, y) {
        return x + y;
    }
}

Math.add(2, 2);

import Math.*;
add(2,2);
But not much implements that yet.

        Why do we care?
       I’ll get to that later.
Platform Consistency
Everyone knows that the biggest suckage in modern
    JavaScript is dealing with different platforms.
Polyfill

A shim that mimics a future API, providing
 fallback functionality to older browsers.




            http://stateofhtml5.appspot.com/
You can fake a surprising amount now days.
;(function(geolocation){

  if (geolocation) return;

  var cache;

 geolocation = window.navigator.geolocation = {};
 geolocation.getCurrentPosition = function(callback){

      if (cache) callback(cache);

      $.getScript('//www.google.com/jsapi',function(){

       cache = {
         coords : {
           "latitude": google.loader.ClientLocation.latitude,
           "longitude": google.loader.ClientLocation.longitude
         }
       };

     callback(cache);
   });

 };

 geolocation.watchPosition = geolocation.getCurrentPosition;

})(navigator.geolocation);
border-radius: 8px;
box-shadow: #666 0px 2px 3px;
background: linear-gradient(#eeff99, #66ee33);
behavior: url(/PIE.htc);




                   http://css3pie.com/
But just because you can,
it doesn’t mean that you should.
But if we are in different environments,
we can start with some polyfills that are much simpler.
Array.prototype.forEach
Array.prototype.map
Array.prototype.filter
Array.prototype.every
Array.prototype.some
Array.prototype.reduce
Array.prototype.indexOf
Object.keys
Date.now
Date.prototype.toISOString
Function.prototype.bind
String.prototype.trim
['one', 'two', 'three'].map(function(word) {
    return word.length
}).filter(function(length) {
    return length > 3;
});
It is not seldom that you see people messing with
Object.prototype.This is very bad because it breaks the
        object-as-hash-tables feature in javascript.
  Array.prototype.map = function() {...};

  var arr = [1,2,3];

  for (var p in arr) {
      console.log(p);
  }

  //     1
  //     2
  //     3
  //     map - erm, what?
http://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
Array.prototype.map = function() {...};

var arr = [1,2,3];

for (var p in arr) {
    if (arr.hasOwnProperty(p)) {
        console.log(p);
    }
}
So where we can polyfill basic language functionality,
              take advantage of it.




                https://github.com/kriskowal/es5-shim
Harmony
JavaScript is the x86 of the web
     - Brendan Eich (creator of JavaScript)
Google Traceur - JavaScript to JavaScript Compiler




              http://code.google.com/p/traceur-compiler/
Harmony Features
                      Modules
                      Iterators
               Iterators and For Each
                     Generators
               Block Scoped Bindings
              Destructuring Assignment
                 Default Parameters
                  Rest Parameters
                  Spread Operator

             Strawman Features
                       Classes
                         Traits
                Deferred Functions
             Object Initializer Shorthand



http://code.google.com/p/traceur-compiler/wiki/LanguageFeatures
Destructuring Assignment




var [a, [b], c] = ['hello', [', ', 'junk'], 'world'];
alert(a + b + c); // hello, world
              http://traceur-testbed.herokuapp.com/destructuringArrayAssignment




                       var pt = {
                          x: 23,
                          y: 42
                       };

                       var {x, y} = pt;

                       console.log(x); // 23
             http://traceur-testbed.herokuapp.com/destructuringObjectAssignment
function slice(list, start = 0, end = list.length) {
    ...
}
               http://traceur-testbed.herokuapp.com/defaultParameters
function print(...items) {
    items.forEach(function(item, index) {
        console.log(index, item);
    });
}

print('foo', 'bar');
// 0, foo
// 1, bar
           http://traceur-testbed.herokuapp.com/restParameters
var a1 = [1,2,3],
    a2 = [];

a2.push(...a1);

// a1.push.apply(a1, a2)

 http://traceur-testbed.herokuapp.com/spreadOperator
Deferred / Promises

var deferred = $.Deferred();
// or dojo.Deferred, new Deferred(), etc...

// Complete the deferred
deferred.resolve(...args);

// Fail the deferred
deferred.reject(...args);

// Return a read-only deferred
deferred.promise();

// Attach handlers for when resolve or rejected
deferred.then(function(...args) { ... }, function(...args) {...});



                       http://wiki.commonjs.org/wiki/Promises
function wait(duration) {
    var deferred = $.Deferred();

    window.setTimeout(function() {
        deferred.resolve();
    });

    return deferred.promise();
}

wait(1000).then(function() {
    alert('done');
});
function deferredWait(timeout) {
    var d = $.Deferred();

    window.setTimeout(function() {
        d.resolve();
    }, timeout);

    return d;
}

function waitOnThings() {
    alert('Starting');
    await deferredWait(1000);
    alert('Finished');
}

        http://traceur-testbed.herokuapp.com/await
Thanks for listening!

JavaScript Growing Up

  • 1.
    JavaScript Growing Up Modules, Platform Consistency and Harmony David Padbury
  • 2.
    Between HTML5 andNode, JavaScript is seeing a staggering level of adoption.
  • 3.
    The patterns andtools and practices that will form the foundation of Modern JavaScript are going to have to come from outside implementations of the language itself - Rebecca Murphey
  • 4.
  • 5.
    Java has import C#has using JavaScript has? Nothing.
  • 6.
    So JavaScript authorsused what we had in the language to provide what we needed.
  • 7.
    But before weget to that, first some prerequisites.
  • 8.
    Everything is global //lib1.js var name = 'Barry'; function sayHi() { alert("Hi, I'm " + name); } <script src="lib1.js"></script> <script> something(); console.log(name); // Barry </script>
  • 9.
    Which could makeincluding multiple libraries challenging // lib1.js function something() { console.log('foo'); } // lib2.js function something() { console.log('bar'); } <script src="lib1.js"></script> <script src="lib2.js"></script> <script> something(); </script>
  • 10.
    Using simple JavaScriptconstructs we can emulate many traditional organization techniques ;(function(lib1) { lib1.something = function() { ... }; })(window.lib1 = window.lib1 || {}); lib1.something(); lib2.something();
  • 11.
    function namespace(ns) { var obj = window; ns.split('.').forEach(function(component) { obj = typeof obj[component] !== 'undefined' ? obj[component] : obj[component] = {}; }); return obj; }
  • 12.
    (function(data) { data.something = function() { ... }; })(namespace('lab49.app.data'));
  • 13.
    (function(example) { function privateAdd(num1, num2) { return num1 + num2; } example.add = function(num1, num2) { return privateAdd(num1, num2); }; })(namespace('lab49.example')); console.log(typeof example.add); // function console.log(typeof example.privateAdd); // undefined console.log(typeof privateAdd); // undefined
  • 14.
    Server-side JavaScript authorsstarted to talk about what a more robust module system would look like.
  • 15.
    I generally supportthe CommonJS idea, but let’s be clear: it’s hardly a specification handed down by the gods (like ES5); it’s just some people discussing ideas on a mailing list. Most of these ideas are without actual implementations. - Ryan Dahl (creator of node.js)
  • 16.
    Introduced a simpleAPI for dealing with modules. require for importing a module. exports for exposing stuff from a module. http://wiki.commonjs.org/wiki/Modules/1.1.1
  • 17.
    // math.js exports.add =function() { var sum = 0, i = 0, args = arguments, l = args.length; while (i < l) { sum += args[i++]; } return sum; }; //increment.js var add = require('math').add; exports.increment = function(val) { return add(val, 1); }; // program.js var inc = require('increment').increment; var a = 1; inc(a); // 2
  • 18.
    CommonJS modules arenow the de-facto for server based JavaScript.
  • 19.
    var http =require('http'); var server = http.createServer(function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hi Lab!'); });
  • 20.
    There are nowa number of tools to bring CommonJS modules to the browser. https://github.com/substack/node-browserify https://github.com/sstephenson/stitch
  • 21.
    var stitch =require('stitch'); var express = require('express'); var package = stitch.createPackage({ paths: [__dirname + '/lib', __dirname + '/vendor'] }); var app = express.createServer(); app.get('/application.js', package.createServer()); app.listen(3000);
  • 22.
    There are someproblems with using this module format in the browser.
  • 23.
    Asynchronous Module Definition (Commonly known as AMD) https://github.com/amdjs/amdjs-api/wiki/AMD
  • 24.
    define for creatinga module definition.
  • 25.
    define('personView', ['models/person'], function(person){ return { initialize: function() { ... } }; });
  • 26.
    AMD is nowused by RequireJS, Dojo and even Node.
  • 27.
    RequireJS also supportstext templates.
  • 28.
    Becoming the mostcommon way to structure large JavaScript applications, both on the server and in the browser.
  • 29.
    JS.next will beintroducing language level modules. These are similar to the modules we’ve been looking at.
  • 30.
    module Math { export function add(x, y) { return x + y; } } Math.add(2, 2); import Math.*; add(2,2);
  • 31.
    But not muchimplements that yet. Why do we care? I’ll get to that later.
  • 32.
  • 33.
    Everyone knows thatthe biggest suckage in modern JavaScript is dealing with different platforms.
  • 34.
    Polyfill A shim thatmimics a future API, providing fallback functionality to older browsers. http://stateofhtml5.appspot.com/
  • 35.
    You can fakea surprising amount now days.
  • 36.
    ;(function(geolocation){ if(geolocation) return; var cache; geolocation = window.navigator.geolocation = {}; geolocation.getCurrentPosition = function(callback){ if (cache) callback(cache); $.getScript('//www.google.com/jsapi',function(){ cache = { coords : { "latitude": google.loader.ClientLocation.latitude, "longitude": google.loader.ClientLocation.longitude } }; callback(cache); }); }; geolocation.watchPosition = geolocation.getCurrentPosition; })(navigator.geolocation);
  • 37.
    border-radius: 8px; box-shadow: #6660px 2px 3px; background: linear-gradient(#eeff99, #66ee33); behavior: url(/PIE.htc); http://css3pie.com/
  • 38.
    But just becauseyou can, it doesn’t mean that you should.
  • 39.
    But if weare in different environments, we can start with some polyfills that are much simpler.
  • 40.
  • 41.
    ['one', 'two', 'three'].map(function(word){ return word.length }).filter(function(length) { return length > 3; });
  • 42.
    It is notseldom that you see people messing with Object.prototype.This is very bad because it breaks the object-as-hash-tables feature in javascript. Array.prototype.map = function() {...}; var arr = [1,2,3]; for (var p in arr) { console.log(p); } // 1 // 2 // 3 // map - erm, what? http://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
  • 43.
    Array.prototype.map = function(){...}; var arr = [1,2,3]; for (var p in arr) { if (arr.hasOwnProperty(p)) { console.log(p); } }
  • 44.
    So where wecan polyfill basic language functionality, take advantage of it. https://github.com/kriskowal/es5-shim
  • 45.
  • 47.
    JavaScript is thex86 of the web - Brendan Eich (creator of JavaScript)
  • 48.
    Google Traceur -JavaScript to JavaScript Compiler http://code.google.com/p/traceur-compiler/
  • 49.
    Harmony Features Modules Iterators Iterators and For Each Generators Block Scoped Bindings Destructuring Assignment Default Parameters Rest Parameters Spread Operator Strawman Features Classes Traits Deferred Functions Object Initializer Shorthand http://code.google.com/p/traceur-compiler/wiki/LanguageFeatures
  • 50.
    Destructuring Assignment var [a,[b], c] = ['hello', [', ', 'junk'], 'world']; alert(a + b + c); // hello, world http://traceur-testbed.herokuapp.com/destructuringArrayAssignment var pt = { x: 23, y: 42 }; var {x, y} = pt; console.log(x); // 23 http://traceur-testbed.herokuapp.com/destructuringObjectAssignment
  • 51.
    function slice(list, start= 0, end = list.length) { ... } http://traceur-testbed.herokuapp.com/defaultParameters
  • 52.
    function print(...items) { items.forEach(function(item, index) { console.log(index, item); }); } print('foo', 'bar'); // 0, foo // 1, bar http://traceur-testbed.herokuapp.com/restParameters
  • 53.
    var a1 =[1,2,3], a2 = []; a2.push(...a1); // a1.push.apply(a1, a2) http://traceur-testbed.herokuapp.com/spreadOperator
  • 54.
    Deferred / Promises vardeferred = $.Deferred(); // or dojo.Deferred, new Deferred(), etc... // Complete the deferred deferred.resolve(...args); // Fail the deferred deferred.reject(...args); // Return a read-only deferred deferred.promise(); // Attach handlers for when resolve or rejected deferred.then(function(...args) { ... }, function(...args) {...}); http://wiki.commonjs.org/wiki/Promises
  • 55.
    function wait(duration) { var deferred = $.Deferred(); window.setTimeout(function() { deferred.resolve(); }); return deferred.promise(); } wait(1000).then(function() { alert('done'); });
  • 56.
    function deferredWait(timeout) { var d = $.Deferred(); window.setTimeout(function() { d.resolve(); }, timeout); return d; } function waitOnThings() { alert('Starting'); await deferredWait(1000); alert('Finished'); } http://traceur-testbed.herokuapp.com/await
  • 57.