Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Ten useful JavaScript tips & best practices

2,801 views

Published on

In this presentation there are ten useful JavaScript techniques which can be included in your application easily with less friction along with some AngularJs tips and best practices as a bonus. These tips and best practices are accompanied by examples & will cover script loading, design pattern, performance optimization and other areas.

Since best practices are very subjective topics, proper benchmarking needs to be done.

Published in: Technology

Ten useful JavaScript tips & best practices

  1. 1. Ten Useful JavaScript Tips & Best Practices
  2. 2. I Am Ankit Rastogi a passionate Learner Website : http://ankitrastogi.com
  3. 3. Stages of Learning Shuhari - first learn, then detach, and finally transcend Shu - “Obey” ha - “Detach” ri - “Separate”
  4. 4. 1 Method Chaining It is a technique for calling multiple functions on the same object consecutively. new Employee() .setName("Ankit") .setDesignation("Consultant") .setDepartment("Engineering") .save();
  5. 5. var Employee = function() { this.name = "Default Name"; this.designation = "Default Designation"; this.department = "Default Department"; }; Employee.prototype.setName = function(name) { this.name = name; return this; }; Employee.prototype.save = function() { console.log("Saving the Employee information in database"); return this; };
  6. 6. 2 Event Delegation Allows you to avoid adding event listeners to specific nodes; instead, the event listener is added to one parent. <ul id="parent-list"> <li id="post-1">Item 1</li> <li id="post-2">Item 2</li> . . . <li id="post-5oo">Item 500</li> </ul>
  7. 7. function getEventTarget(e) { e = e || window.event; return e.target || e.srcElement; } // Get the element, add a click listener... document.getElementById("parent-list").addEventListener("click", function(e) { var target = getEventTarget(e); // e.target is the clicked element! // If it was a list item if(target && target.nodeName == "LI") { // List item found! Output the ID! } });
  8. 8. 3 Debounce Postpone the passed function execution until after wait milliseconds have elapsed since the last time it was invoked. var lazyLayout = debounce(250, function() { // This code gets executed after // 250 ms have passed since the last // invoked time }); $(window).resize(lazyLayout);
  9. 9. function debounce(delay, callback) { 2 var timeout = null; return function () { // // if a timeout has been registered before then // cancel it so that we can setup a fresh timeout // if (timeout) { clearTimeout(timeout); } var context = this; var args = arguments; timeout = setTimeout(function () { callback.apply(context, args); timeout = null; }, delay); }; }
  10. 10. 4 Throttle Call the original function at most once per every wait milliseconds. var scrollHandler = throttle(250, function() { // This code gets executed after // 250 ms have passed. }); $(window).scroll(scrollHandler);
  11. 11. function throttle(delay, callback) { var previousCall = new Date().getTime(); return function() { var time = new Date().getTime(); // // if "delay" milliseconds have expired since // the previous call then propagate this call to // "callback" // if ((time - previousCall) >= delay) { previousCall = time; callback.apply(null, arguments); } }; }
  12. 12. 5 Method Queue Pattern Popularized by Google Analytics tracking code. Also known as asynchronous function queuing. // onClick event is tracked by google analytics <a href="#" onClick="_gaq.push(['_trackEvent', 'Videos', 'Play', 'Description of Video']);" >Play</a>
  13. 13. var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-XXXXX-X']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https: //ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s. parentNode.insertBefore(ga, s); })();
  14. 14. // get the existing _gaq array var _old_gaq = window._gaq; // create a new _gaq object window._gaq = new GoogleAnalyticsQueue(); // execute all of the queued up events - apply() turns // the array entries into individual arguments window._gaq.push.apply(window._gaq, _old_gaq); 2
  15. 15. var GoogleAnalyticsQueue = function () { this.push = function () { for (var i = 0; i < arguments.length; i++) try { 2 if (typeof arguments[i] === "function") arguments[i](); else { // get tracker function from arguments[i][0] // get tracker function arguments from // arguments[i].slice(1) // call it! // trackers[arguments[i][0]] // .apply(trackers,arguments[i].slice(1)); } } catch (e) {} } // more code here… };
  16. 16. 6 Plus Operator Convert anything to a number. // Quick hex to dec conversion: +"0xFF"; // -> 255 // Get a timestamp for now, the equivalent of `new Date().getTime()`: +new Date(); // for shortening something like if (someVar === null) someVar = 0; +null; // -> 0;
  17. 17. // Safer parsing than parseFloat()/parseInt() parseInt("1,000"); // -> 1, not 1000 +"1,000"; // -> NaN, much better for testing user input parseInt("010"); // -> 8, because of the octal literal prefix +"010"; // -> 10, `Number()` doesn't parse octal literals 2 // Boolean to integer +true; // -> 1; +false; // -> 0; // Other useful tidbits: +"1e10"; // -> 10000000000 +"1e-4"; // -> 0.0001 +"-12"; // -> -12
  18. 18. var rnd = { "valueOf": function () { return Math.floor(Math.random()*1000); } 2 }; +rnd; // -> 442; +rnd; // -> 727; +rnd; // -> 718;
  19. 19. 7 Shorten Scope Chains Global Namespace is crowded. Javascript Look Up first in local than global. Use local variables to cache global one. var a = function(){ var doc = document, blah = doc.getElementById('myID'), blah2 = doc.getElementById('myID2'); }
  20. 20. 2 var aGlobalVar = 1; function doSomething(val) { var i = 1000, agv = aGlobalVar; while (i--) { agv += val; }; aGlobalVar = agv; }; doSomething(10);
  21. 21. 8 Memoization It is a programming technique which attempts to increase a function’s performance by caching its previously computed results. var costlyOperation = function(a){ // Time consuming operations }; memoizedOperation = memoize(costlyOperation); memoizedOperation(a);
  22. 22. function memoize( f ) { return function () { 2 var args = Array.prototype.slice.call(arguments); //we've confirmed this isn't really influencing //speed positively f.memoize = f.memoize || {}; //this is the section we're interested in return (args in f.memoize)? f.memo[args] : f.memoize[args] = f.apply(this, args); }; }
  23. 23. 9 Lazy JS Parsing Minimizing JavaScript parse time. Increase performance especially in mobile. <html> ... <script id="lazy"> /* JavaScript of lazy module */ </script>
  24. 24. <script> function lazyLoad() { 2 var lazyElement = document.getElementById('lazy'); var lazyElementBody = lazyElement.innerHTML; var jsCode = stripOutCommentBlock(lazyElementBody); eval(jsCode); } </script> <div onclick=lazyLoad()> Lazy Load </div> </html>
  25. 25. 10 DOM Manipulation
  26. 26. Identify the problem? function updateAllAnchors(element, anchorClass) { var anchors = element.getElementsByTagName('a'); for (var i = 0, length = anchors.length; i < length; i ++) { anchors[i].className = anchorClass; } }
  27. 27. function removeToInsertLater(element) { 2 var parentNode = element.parentNode; var nextSibling = element.nextSibling; parentNode.removeChild(element); return function() { if (nextSibling) { parentNode.insertBefore(element, nextSibling); } else { parentNode.appendChild(element); } }; } Solution
  28. 28. function updateAllAnchors(element, anchorClass) { var insertFunction = removeToInsertLater(element); var anchors = element.getElementsByTagName('a'); for (var i = 0, length = anchors.length; i < length; i ++) { 2 anchors[i].className = anchorClass; } insertFunction(); } Solution
  29. 29. Identify the problem? function addAnchors(element) { var anchor; for (var i = 0; i < 10; i ++) { anchor = document.createElement('a'); anchor.innerHTML = 'test'; element.appendChild(anchor); } }
  30. 30. function addAnchors(element) { var anchor, fragment = document.createDocumentFragment(); for (var i = 0; i < 10; i ++) { 2 anchor = document.createElement('a'); anchor.innerHTML = 'test'; fragment.appendChild(anchor); } element.appendChild(fragment); } Solution
  31. 31. Bonus Identify the problem
  32. 32. 2 Identify the problem baz.Bar = function() { // constructor body this.foo = function() { // method body }; }
  33. 33. 2 baz.Bar = function() { // constructor body } baz.Bar.prototype.foo = function() { // method body }; Solution
  34. 34. 2 Identify the problem foo.Bar = function() { this.prop1_ = 4; this.prop2_ = true; this.prop3_ = []; this.prop4_ = 'blah'; };
  35. 35. 2 Solution foo.Bar = function() { this.prop3_ = []; }; foo.Bar.prototype.prop1_ = 4; foo.Bar.prototype.prop2_ = true; foo.Bar.prototype.prop4_ = 'blah';
  36. 36. 2 function setupAlertTimeout() { var msg = 'Message to alert'; window.setTimeout(function() { alert(msg); }, 100); } Identify the problem
  37. 37. 2 function setupAlertTimeout() { window.setTimeout(function() { var msg = 'Message to alert'; alert(msg); }, 100); } Solution?
  38. 38. 2 function alertMsg() { var msg = 'Message to alert'; alert(msg); } function setupAlertTimeout() { window.setTimeout(alertMsg, 100); } Solution
  39. 39. 2 var divs = document.getElementsByTagName('div'); for (var i=0; i < divs.length; i++ ) { var div = document.createElement("div"); document.appendChild(div); } Identify the problem
  40. 40. function array(items) { 2 try { return Array.prototype.concat.call(items); } catch (ex) { var i = 0, len = items.length, result = Array(len); while (i < len) { result[i] = items[i]; i++; } return result; } } Solution
  41. 41. 2var divs = array( document.getElementsByTagName('div') ); for (var i=0; i < divs.length; i++ ) { var div = document.createElement("div"); document.appendChild(div); } Solution
  42. 42. Bonus Angular Js
  43. 43. Cache Factory var cache = $cacheFactory('cacheId'); expect($cacheFactory.get('cacheId')).toBe(cache); expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined(); 2 cache.put("key", "value"); cache.put("another key", "another value"); // We've specified no options on creation expect(cache.info()).toEqual({id: 'cacheId', size: 2});
  44. 44. ng-repeat with track by <ul class="tasks"> <li ng-repeat="task in tasks" ng-class="{done: task. 2 done}"> {{task.id}}: {{task.title}} </li> </ul> $scope.tasks = newTasksFromTheServer;
  45. 45. ng-repeat with track by 2 ng-repeat="task in tasks track by task.id"
  46. 46. $parse, $interpolate, $compile 2 var imgHtml = '<img ng-src="/path/{{name}}.{{extension}}">' $scope.name = 'image'; $scope.extension = 'jpg';
  47. 47. $parse, $interpolate, $compile $parse is concerned with individual expressions only (name, extension). It is a read-write service. 2 $interpolate is read only and is concerned with strings containing multiple expressions (/path/{{name}}.{{extension}}) $compile is at the heart of AngularJS machinery and can turn HTML strings (with directives and interpolation expressions) into live DOM.
  48. 48. Q & A
  49. 49. References : ● http://davidwalsh.name/event-delegate ● http://underscorejs.org/ ● http://blogorama.nerdworks.in/javascriptfunctionthrottlingan/ ● http://mrcoles.com/blog/google-analytics-asynchronous-tracking-how-it-work/ ● http://stackoverflow.com/questions/61088/hidden-features-of-javascript ● http://archive.devwebpro.com/devwebpro-39-20030514OptimizingJavaScriptforExecutionSpeed.html ● http://www.sitepoint.com/implementing-memoization-in-javascript/ ● http://googlecode.blogspot.in/2009/09/gmail-for-mobile-html5-series-reducing.html ● https://developers.google.com/speed/articles/javascript-dom ● http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/ ● https://developers.google.com/speed/articles/optimizing-javascript ● https://docs.angularjs.org/api/ng/service/$cacheFactory ● http://www.codelord.net/2014/04/15/improving-ng-repeat-performance-with-track-by/ ● http://stackoverflow.com/questions/17900588/what-is-the-difference-between-the-parse-interpolate-and-compile- services
  50. 50. Thank you

×