to Build Modular JavaScript Tim Perry Tech Lead & Open-Source Champion at Softwire @pimterry / github.com/pimterry / tim-perry.co.uk Tim Perry Tech Lead & Open-Source Champion at Softwire @pimterry / github.com/pimterry / tim-perry.co.uk
over 10 days ‘or something worse than JS would have happened’ Renamed to JavaScript three months later to confuse as many people as possible for marketing purposes Everybody implements subtly different versions First spec published in June 1997 (now as ECMAScript) First designed & implemented by Brendan Eich over 10 days ‘or something worse than JS would have happened’ Renamed to JavaScript three months later to confuse as many people as possible for marketing purposes Everybody implements subtly different versions First spec published in June 1997 (now as ECMAScript)
functions & closures Asynchronous everything Some ‘features’ that need removing: The ‘with’ keyword Much of type coercion Automatic semicolon insertion Some great bits: Dynamic typing First-order functions & closures Asynchronous everything Some ‘features’ that need removing: The ‘with’ keyword Much of type coercion Automatic semicolon insertion Some hugely counter-intuitive fundamentals: How ‘this’ and variable scope work Prototypes Some clearly relevant features that don’t exist: Simple class definitions Tail-call optimizations A mechanism to allow structured modular code Some hugely counter-intuitive fundamentals: How ‘this’ and variable scope work Prototypes Some clearly relevant features that don’t exist: Simple class definitions Tail-call optimizations A mechanism to allow structured modular code
either in local scope or global scope JavaScript uses lexically-defined function scoping Variables definitions are either in local scope or global scope function f() { var localVar = “a string”; } function f(localParameter) { localParameter = “a string”; } function f() { function localFunction() { } } function f() { var localVar = “a string”; } function f(localParameter) { localParameter = “a string”; } function f() { function localFunction() { } } var globalVar = “a string”; function g() { globalVar = “a string”; } function g() { window.globalVar = “a string”; } var globalVar = “a string”; function g() { globalVar = “a string”; } function g() { window.globalVar = “a string”; }
Dependencies are explicitly defined (if only by the global variables they manage) Code is reusable (in contexts where dependencies are already available globally) Code internals are encapsulated Dependencies are explicitly defined (if only by the global variables they manage) Code is reusable (in contexts where dependencies are already available globally)
be used to store each module Namespacing requires manual initialization and management Module loading and ordering have to be managed manually Moderate amount of boilerplate Global state has to be used to store each module Namespacing requires manual initialization and management Module loading and ordering have to be managed manually Moderate amount of boilerplate
“coffeeMachine/grinder”], function ($, ko, coffeeGrinder) { [… make coffee or build some private state or something …] return { “doSomethingCoffeeRelated” : coffeeMakingFunction, “usefulNumber” : 4, }; } ); define([“lib/jquery”, “lib/knockout”, “coffeeMachine/grinder”], function ($, ko, coffeeGrinder) { [… make coffee or build some private state or something …] return { “doSomethingCoffeeRelated” : coffeeMakingFunction, “usefulNumber” : 4, }; } );
reusable Explicitly named dependencies Dependency loading is asynchronous Implementable in vanilla JavaScript only Powerful plugin architecture Code internals are encapsulated Code is reusable Explicitly named dependencies Dependency loading is asynchronous Implementable in vanilla JavaScript only Powerful plugin architecture
Can’t handle circular dependencies Can result in code that requires many HTTP requests to pull down its large dependency network (solvable with R.js or similar) Lots of boilerplate Lots of complexity Can’t handle circular dependencies Can result in code that requires many HTTP requests to pull down its large dependency network (solvable with R.js or similar)
CouchDB, Narwhal The native environment for CommonJS modules Synchronous loading makes perfect sense server-side Closer model to non-browser scripting languages Browserify Require.js Various non-browser platforms Node.JS, CouchDB, Narwhal The native environment for CommonJS modules Synchronous loading makes perfect sense server-side Closer model to non-browser scripting languages Browserify Require.js
CommonJS modules for the browser Build tool that takes CommonJS modules and compiles the whole app into a single script file Lets node.js modules work directly in a browser Require.js Various non-browser platforms Browserify CommonJS modules for the browser Build tool that takes CommonJS modules and compiles the whole app into a single script file Lets node.js modules work directly in a browser Require.js
Dependencies are explicitly named Code is easily reusable Simple clean syntax and conceptual model Basically no boilerplate Handles circular references better than AMD Code internals are encapsulated Dependencies are explicitly named Code is easily reusable Simple clean syntax and conceptual model Basically no boilerplate Handles circular references better than AMD
Doesn’t follow standard JavaScript conventions No consideration of environment where loads are expensive Ignores JavaScript’s inherent asynchronicity Dependencies aren’t necessarily all obvious upfront Lots of magic involved Doesn’t follow standard JavaScript conventions No consideration of environment where loads are expensive Ignores JavaScript’s inherent asynchronicity Dependencies aren’t necessarily all obvious upfront
well supported everywhere (eventually) Extremely powerful New syntax, but otherwise true to existing JS semantics Low on boilerplate Handles circular references excellently Similar to other language concepts & syntax Semi-synchronous Likely to be well supported everywhere (eventually) Extremely powerful New syntax, but otherwise true to existing JS semantics Low on boilerplate Handles circular references excellently Similar to other language concepts & syntax Semi-synchronous
nowhere Not even final in the spec yet Lots of genuinely new syntax import * is included, but frowned upon in every other language Powerful, but thereby potentially very complicated Currently supported effectively nowhere Not even final in the spec yet Lots of genuinely new syntax import * is included, but frowned upon in every other language Powerful, but thereby potentially very complicated
IIFE: For tiny projects For trivial compatibility AMD: For most serious browser-based projects For a no-build pure-JS solution If you need to depend on non-JS content/events CommonJS: For anything outside a browser environment For anything in a browser where you might want Node modules ES6: If you yearn for the extremely bleeding edge And you live way in the future where it has real support IIFE: For tiny projects For trivial compatibility AMD: For most serious browser-based projects For a no-build pure-JS solution If you need to depend on non-JS content/events CommonJS: For anything outside a browser environment For anything in a browser where you might want Node modules ES6: If you yearn for the extremely bleeding edge And you live way in the future where it has real support
Champion at Softwire @pimterry / github.com/pimterry / tim-perry.co.uk Tim Perry Tech Lead & Open-Source Champion at Softwire @pimterry / github.com/pimterry / tim-perry.co.uk