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

Writing Maintainable and Reusable JavaScript

Writing Maintainable and Reusable JavaScript

It’s really easy for JavaScript files in a theme or plugin to quickly become a big, hairy mess. So let’s take a look at how to structure JavaScript code in a way that makes it easier to read and understand, easier to maintain, and prevents pollution of the global namespace. We’ll cover modular JavaScript structure and writing plugins.

Natalie MacLees

November 08, 2014
Tweet

More Decks by Natalie MacLees

Other Decks in Technology

Transcript

  1. Writing Maintainable & Reusable JavaScript by Natalie MacLees @nataliemac |

    nataliemac.com
  2. Why is maintainability important?

  3. JavaScript mistakes you’re probably making

  4. Writing all your code inside document ready jQuery(document).ready(function($){ function slideShow()

    { // some code that makes a slideshow } ! function newsTicker() { // some code that makes a news ticker } ... });
  5. Using global scope for all your variables and functions var

    newText = ‘Hello World’; ! function addText() { var container = $(‘textContainer’); container.text(newText); } ! var height = window.height();
  6. Inconsistently using style conventions var newText = ‘Hello World!”; !

    var some_other_text = “Hi there!”; ! var yetSomeMoreText = “Bonjour!”;
  7. Not maintaining separation <a href=“#” onclick=“doSomething();”>Click me!</a> $(‘a’).css({
 ‘color’: ‘green’;


    ‘fontSize’: ‘2em’;
 }); var lightbox = $(‘<div class=“overlay”></div><div class=“lightbox”><img src=“”/><div class=“lightbox- title”></div></div>’);
  8. The wild, wild West of JavaScript

  9. Understandable Future-proof Readable Modifiable Extensible Testable What does maintainable &

    reusable mean?
  10. Writing better JavaScript 1 2 3 4 5 Style conventions

    Programming practices Modular pattern jQuery plugins Automation
  11. 1 Style conventions

  12. Spaces vs tabs

  13. Keep lines as short as possible if ( tod ==

    ‘morning’ ) { $(‘.greeting’).text(‘Good morning’) } else { $(‘.greeting’).text(‘Good afternoon!’) } ! $ (‘ul’).slideDown().find(‘li’).addClass(‘open’).prepe nd(‘+’).end().addClass(‘parent-open’);
  14. Keep lines as short as possible $(‘ul’) .slideDown() .find(‘li’) .addClass(‘open’)

    .prepend(‘+’) .end() .addClass(‘parent-open’);
  15. Use comments like salt in soup

  16. Use logical names for functions and variables (even if they’re

    long)
  17. Use camelCase

  18. camelCase & abbreviations and acronynms getElementById() innerHTML() XMLHttpRequest()

  19. 2 Programming practices

  20. Keep layers separate CSS: .highlight {
 color: green;
 fontSize: 2em;


    } JavaScript: $(‘a’).addClass(‘highlight’);
  21. Keep layers separate <div class="entry"> <h1>{{title}}</h1> <div class="body"> {{body}} </div>

    </div>
  22. Don’t modify objects you don’t own

  23. Event handlers should only handle events $(‘.next’).on(‘click’, function(){ var slider

    = $(‘#slider’), currentSlide = slider.find(‘.current’), nextSlide = currentSlide.next(); currentSlide.fadeOut(); nextSlide.fadeIn(); });
  24. Event handlers should only handle events $(‘.next’).on(‘click’, function(){ nextSlide(); });

    ! function nextSlide() { // code to advance to next slide here }
  25. Throw your own errors Twitlicious.addTweets = function(container) { if (

    container instanceof jQuery) { container.append(Twitlicious.tweets); } else { throw new Error “addTweets: This is not a jQuery object!”; } }
  26. Separate config data var config = { url: ‘https://api.twitter.com/...', tweetsToShow:

    5, tweetContainer: $(‘#tweets’) };
  27. Avoid global functions & variables

  28. 3 Modular Pattern

  29. Object literal var projectName = { config: { numberofTweets: 5,

    url: ‘http://api.twitter.com...', container: $(‘tweets’) }, init: function() { // get everything going }, ...
  30. Object literal jQuery(function(){ projectName.init(); }; ! var projectName = {

    config: { ... }, init: function() { // initialize the project } }
  31. Immediately invoked function expression (IIFE) ;(function ($, projectName, undefined) {

    var linkClick = function() { // private $(‘a’).on(‘click’, function(){ //do something when links are clicked }); }; projectName.init = function() { // public linkClick(); }; }(jQuery, window.projectName = window.projectName || {})); ! jQuery(function(){ projectName.init(); });
  32. 4 jQuery plugins

  33. Use an immediately invoked function expression ;(function($){ $.fn.venturaSlider = function(options){

    // Plugin code goes here } })(jQuery);
  34. window, document, undefined ;(function($, window, document, undefined){ $.fn.venturaSlider = function(options){

    // Plugin code goes here } })(jQuery, window, document);
  35. Iterate over each item in the collection ;(function($, window, document,

    undefined){ $.fn.venturaSlider = function(options){ this.each(function(){ // Do something to each item }); } })(jQuery, window, document);
  36. Use .data() to store instance details ;(function($, window, document, undefined){

    $.fn.venturaSlider = function(options){ this.each(function(){ var $this = $(this); $this.data(‘current’, 1); }); } })(jQuery, window, document);
  37. Allow customization & use extend() ;(function($, window, document, undefined){ $.fn.venturaSlider

    = function(options){ var opts = $.extend( {}, $.fn.venturaSlider.defaults, options); ... } $.fn.venturaSlider.defaults = { // Define default settings }; })(jQuery, window, document);
  38. Return the jQuery object for chaining ;(function($, window, document, undefined){

    $.fn.venturaSlider = function(options){ var opts = $.extend( {}, $.fn.venturaSlider.defaults, options); ... return this; } $.fn.venturaSlider.defaults = {}; })(jQuery, window, document);
  39. 5 Automation

  40. Break JavaScript into multiple files

  41. Minify, compress, & deploy

  42. Maintainable & reusable code matters 1 2 3 4 5

    Style conventions Programming practices Modular pattern jQuery plugins Automation
  43. –Rick Osborne, creator of TorrentSpy “Always code as if the

    person who ends up maintaining your code is a violent psychopath who knows where you live.”
  44. –Chris Eppstein, creator of Compass “Be kind to your future

    self.”
  45. Thank you! Questions?