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

Taking JavaScript Seriously (feat. Backbone.js)

Taking JavaScript Seriously (feat. Backbone.js)

A talk I gave on 'Taking JavaScript Seriously', talking about why you should be taking JavaScript seriously, how to improve your JavaScript by avoiding some common pitfalls, and using Backbone.js to make larger applications easier to build and maintain.

James Cox-Morton

November 21, 2011
Tweet

More Decks by James Cox-Morton

Other Decks in Programming

Transcript

  1. Most people don’t bother People use JavaScript because they have

    to, and expect it to work like <SOME OTHER LANGUAGE>
  2. Most people don’t bother Unfortunately... People use JavaScript because they

    have to, and expect it to work like <SOME OTHER LANGUAGE>
  3. The Bad Parts Dependency on global variables No block scope

    Prototypal inheritance is unintuitive to OO programmers
  4. The Bad Parts Dependency on global variables No block scope

    Prototypal inheritance is unintuitive to OO programmers Many other small problems which you expect from a language written in 10 days
  5. Avoiding Globals //Create a global variable var MYAPP = {};

    //Put globals into it MYAPP.map = new Map()
  6. Function scope, not block scope var hat; // This is

    global function() { for (var i = 0, il = 10; i < il; i++) { // boat is not limited to the block.. var boat = ‘great’; } // i, il and boat are still in scope here... } // ... but only hat remains here
  7. Define all vars at beginning of their scope function() {

    // Define ALL your vars here var i, il, boat; for (i = 0, il = 10; i < il; i++) { boat = ‘great’; } }
  8. Closure var closureExample = (function() { var mcHammer = "Can't

    touch this"; return { hammerTime: function () { mcHammer = 'Stop! Hammer time'; }, hammerSay: function () { alert(mcHammer); } }; }()); closureExample.mcHammer; //Will throw an error closureExample.hammerSay();// “Can’t touch this” closureExample.hammerTime(); closureExample.hammerSay();// “Stop! Hammer time
  9. Objects inherit from other objects: Should be simple! Unfortunately, JavaScript’s

    tries to make this as unintuitive as possible by using a pseudoclassical pattern :-| No Classes
  10. Pseudoclassical behaviour using ‘new’ // New vehicle object var Vehicle

    = function (color) { this.color = color; }; // Augment the prototype with a function Vehicle.prototype.getColor = function () { alert(“I’m “ + this.color); }; // Make an instance var vehicle = new Vehicle(‘Red’); vehicle.getColor(); // “I’m Red”
  11. var Car = function(color) { this.color = color; this.noise =

    ‘Vroom!’; } Car.prototype = new Vehicle(); Car.prototype.describe = function () { alert(‘The ‘ + this.color + ‘ car goes ’ + this.noise); } var car = new Car(‘purple’); car.describe(); // The purple car goes Vroom! car.getColor(); // I’m purple
  12. Don’t do it like this! The new keyword sucks It’s

    clumsy to use and forgetting the ‘new’ prefix when calling a constructor is easy to do and hard to debug Instead...
  13. Use functions to create objects with closure Much cleaner that

    the pseudoclassical pattern Closure ensures more robust objects
  14. var vehicle = function(spec) { // Define that and private

    instance variables var that, aPrivateVariable; // Initialise that as an object that = {}; // Create privileged methods var getColor = function () { alert("I’m " + spec.color); }; that.getColor = getColor; // Return our created object return that; }; var myVehicle = vehicle({color:'red'});
  15. var car = function(spec) { spec.noise = spec.noise || 'Vroom!';

    // initialise 'that' as a vehicle, // thereby inheriting from it var that = vehicle(spec); var describe = function () { alert('The ' + spec.color + ' car goes ' + spec.noise); }; that.describe = describe; return that; } var myCar = car({color:'purple'});
  16. JavaScript without the bad parts Super readable, Ruby-like syntax Compiles

    to fast, high quality, human readable JavaScript CoffeeScript
  17. But! Even if you’re not ready to use CoffeeScript in

    your app, it’s still a great way to improve your JavaScript
  18. Play with the interpreter at http://jashkenas.github.com Prototype your code in

    CoffeeScript, learn best practices from the generated output
  19. Models Reuse your existing application models Stores your data and

    the logic to manipulate it Should be pretty familiar!
  20. Song = Backbone.Model.extend({ defaults: {playCount: 0}, initialize: function(){ // Setup

    the model here }, displayName: function (){ // Use .get to get properties this.get(‘artist’) + ‘: ‘ + this.get(‘track’); }, play: function () { //Use .set to set properties this.set({playCount: this.get(‘playCount’) + 1}); } }); song = new Song({artist: ‘The Fall’, track: ‘Barmy’});
  21. Collections var Album = Backbone.Collection.extend({ model: Song }); var song1

    = new Song({ name: "One Touch", artist: "LCD Soundsystem" }); var song2 = new Song({ name: "Song 2", artist: "Blur" }); var compilation = new Album([song1, song2]);
  22. Speak JSON JSON is what your app should be serving

    Super easy to initialise Backbone/Javascript objects: SomeCollection = new Collection({JSON DATA})
  23. Speak JSON JSON is what your app should be serving

    Super easy to initialise Backbone/Javascript objects: Much more reusable than pre-rendered HTML SomeCollection = new Collection({JSON DATA})
  24. Speak JSON JSON is what your app should be serving

    Super easy to initialise Backbone/Javascript objects: Much more reusable than pre-rendered HTML Build a platform! SomeCollection = new Collection({JSON DATA})
  25. Views AlbumView = Backbone.View.extend({ initialize: function(){ // Setup the view

    }, render: function(){ // Visualise something return this; } }); var av = new AlbumView({ collection: Compilation });
  26. initialise: function() { // Create the template from the DOM

    element this.template = _.template($('#album_template').html()) }, render: function() { // Render to this.el with a templating language $(this.el).html(this.template(this.collection.toJSON())); } <script type="text/template" id="album_template"> <ul> <% for (var i = 0; i < songs.length; i++){ %> <li><% employeeList[i].get(‘name’); %></li> <% } %> </ul> </script> Templating
  27. Bind DOM events to view methods AlbumView = Backbone.View.extend({ events:

    { // bind events to methods ‘click .addSong’: ‘addSong’ }, addSong: { // Talk to our collections/model song_name = prompt("Song name?") song_model = new Song({ name: song_name }) } })
  28. Bind Collection/Model events to view.render methods AlbumView = Backbone.View.extend({ initialize:

    { ... this.collection.bind('reset', this.render) this.collection.bind('add', this.render) this.collection.bind('remove', this.render) ... } }
  29. Router Connect routes up to app initialisation Provides browser history

    support and linkable, bookmarkable, shareable URLs
  30. MyApp = Backbone.Router.extend({ routes: { '/': 'index', '/:id/': 'show' },

    initialize: function() { // Do any app wide stuff }, index: function() { if (typeof(window.MYAPP.currentView) !== 'undefined') // Close any existing view //Create a collection myCollection = new Collection({some JSON}) //Create a view window.MYAPP.currentView = new CollectionView({collection: myCollection}) $('#container').html(window.MYAPP.currentView.render().el); } });
  31. // Create the app myApp = new MyApp(); // Fire

    up the history Backbone.history.start({pushState:true}); // Trigger a history event myApp.navigate('/' + model.get(‘id’), true)
  32. Big Recap! Web Apps => Awesome Learn JavaScript => You

    don’t have a choice Backbone.js => Make large JS projects manageable