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.

Expert JavaScript tricks of the masters

1,304 views

Published on

A presentation I gave at Dr. Dobbs India in the cities of Bangalore and Pune.

Published in: Internet, Technology
  • Be the first to comment

Expert JavaScript tricks of the masters

  1. 1. Tricks of the masters Expert JavaScript:
  2. 2. JavaScript can be strange
  3. 3. JavaScript can be strange • Syntactically similar to C++ and Java “Java is to JavaScript as car is to carpet” • Prototypal inheritance • Classless. Objects inherit from objects. • Loosely typed • Type coercion. “Truthy” / “falsy” values. • Objects are mutable
  4. 4. NodeLists
  5. 5. NodeLists Get all the anchors in a page: var anchors1 = document.getElementsByTagName('a'); [<a href="#">​Item 1​</a>, <a href="#">​Item 2​</a>] var anchors2 = document.querySelectorAll('a'); [<a href="#">​Item 1​</a>, <a href="#">​Item 2​</a>]
  6. 6. NodeLists User interaction causes more anchors to be added to the DOM. More content including anchors returned Pagination request to server
  7. 7. NodeLists One of our NodeLists is automatically updated: console.log(anchors1); [<a href="#">​Item 1​</a>, <a href="#">​Item 2​</a>, <a href="#">​Item 3​</a>, <a href="#">​Item 4​</a>] console.log(anchors2); [<a href="#">​Item 1​</a>, <a href="#">​Item 2​</a>]
  8. 8. Scope and Closures
  9. 9. Scope and Closures JavaScript does not have block scope. Sort of.
  10. 10. Scope and Closures Variables are scoped to functions var foo = "bar"; //global function widget() { var foo = "123"; //scoped to widget }
  11. 11. Scope and Closures Variables are scoped to functions var message = 'Hello? Is anybody there?'; function helloWorld() { var message = 'Hello, world!'; return message; } // returns "Hello, world!"
  12. 12. Scope and Closures Functions don't need to be named. A common scoping technique is to use the Immediately-Invoked Function Expression (aka IIFE)
  13. 13. Scope and Closures Immediately-Invoked Function Expression: (function () { var message = 'Hello, world!', conferenceName = 'Dr. Dobbs India', attendees = 'Awesome'; }());
  14. 14. Scope and Closures Immediately-Invoked Function Expression: (function ($) { $('p'); //works }(jQuery)); $('p'); //does not work
  15. 15. Scope and Closures Functions also create closures. Closure = Anything declared within a function is aware of anything else declared within that function.
  16. 16. Scope and Closures Functions also create closures. var public = 'Everybody sees this.'; function family() { var father, mother; function kids() { var child1, child2; } }
  17. 17. Scope and Closures Building a game leveraging closures: var game = (function () { var secret = 5; return function (num) { var total = secret * num; console.log('You say ' + num + ', I say ' + total + '. What is my secret?'); }; }());
  18. 18. Scope and Closures Building a game leveraging closures: > game(5) You say 5, I say 25. What is my secret? > game(10) You say 10, I say 50. What is my secret? > secret ReferenceError: secret is not defined
  19. 19. Scope and Closures Block scope with let* if (x) { let myVar; let yourVar = 123; } * Not yet available everywhere.
  20. 20. Scope and Closures Block scope with let* var myVar = 5; let(myVar = 6) { alert(myVar); // 6 } alert(myVar); // 5 * Not yet available everywhere.
  21. 21. Memoization
  22. 22. Memoization square()
  23. 23. Memoization var square = function (num) { return num * num; };
  24. 24. Memoization Problem: What if the operation is more complex and is called multiple times?
  25. 25. Memoization Trick: Cache the result.
  26. 26. Memoization var square = (function () { var memo = []; return function (num) { var sqr = memo[num]; if (typeof sqr === 'undefined') { console.log('Calculating...'); memo[num] = sqr = num * num; } return sqr; } }());
  27. 27. Memoization var fetchData = (function () { var data = null, timestamp = new Date().getTime(); return function (url, callback) { if (timestamp - new Date().getTime() > 60000) { $.ajax(url, {success: function (d) { timestamp = new Date().getTime(); data = d; callback(data); }); } else { callback(data); } } }());
  28. 28. Function Overloading
  29. 29. Function overloading calculateAverage()
  30. 30. Function overloading > calculateAverage([10, 20, 30, 40, 50]) 30
  31. 31. Function overloading function calculateAverage(values) { var total = 0; values.forEach(function (val) { total += val; }); return total / values.length; }
  32. 32. Function overloading > calculateAverage(10, 20, 30, 40, 50) 30
  33. 33. Function overloading How many arguments are being passed?
  34. 34. Function overloading Use the arguments object. function returnArgs() { return arguments; } > returnArgs('hello', 'world'); ["hello", "world"]
  35. 35. Function overloading arguments is not an Array. Does not have any Array properties except length. Not very useful.
  36. 36. Function overloading arguments can be converted into an array: var args = Array.prototype.slice.call(arguments);
  37. 37. Function overloading function calculateAverage(values) { var total = 0; if (!Array.isArray(values)) { values = Array.prototype.slice.call(arguments); } values.forEach(function (val) { total += val; }); return total / values.length; }
  38. 38. Function overloading > calculateAverage('10, 20, 30, 40, 50') 30
  39. 39. Function overloading function calculateAverage(values) { var total = 0; if (typeof values === 'string') { values = values.split(','); } else if (typeof values === 'number') { values = Array.prototype.slice.call(arguments); } values.forEach(function (val) { total += parseInt(val, 10); }); return total / values.length; }
  40. 40. Async Code Execution
  41. 41. Async Code Execution What does this code do? // Load appointments for April $.ajax('/calendar/2014/04/'); // Show the calendar showCalendar(); Shows an empty calendar.
  42. 42. Async Code Execution Ajax requests are asynchronous. The JavaScript engine doesn’t wait. // Load appointments for April $.ajax('/calendar/2014/04/'); // Show the calendar showCalendar();
  43. 43. Async Code Execution Event-driven programming where callback functions are assigned as event handlers. When X happens, do Y. Where X is the event and Y is the code to execute.
  44. 44. Async Code Execution Assigning an Ajax event handler: // Load appointments for April $.ajax('/calendar/2014/04/', { complete: showCalendar });
  45. 45. Async Code Execution Event handler assignment: document.onclick = function (e) { e = e || event; console.log('Mouse coords: ', e.pageX, ' / ', e.pageY); }
  46. 46. Async Code Execution Event handler assignment: document.addEventListener('click', function (e) { e = e || event; console.log('Mouse coords: ', e.pageX, ' / ', e.pageY); }); document.addEventListener('click', function (e) { e = e || event; var target = e.target || e.srcElement; console.log('Click target: ', target); });
  47. 47. Async Code Execution Event handler assignment: var xhr = new XMLHttpRequest(); xhr.onload = function () { console.log(this.responseText); } xhr.open('get', ’/weather_data'); xhr.send();
  48. 48. Async Code Execution Event handler context: document.onclick = function (e) { // `this` refers to document object e = e || event; console.log('Mouse coords: ', e.pageX, ' / ', e.pageY); }
  49. 49. Async Code Execution Event handler context: xhr.onload = function () { // `this` refers to xhr object console.log(this.responseText); }
  50. 50. Async Code Execution this refers to XMLHttpRequest object:
  51. 51. Execution Context
  52. 52. Execution Context Need to execute callback in different contexts where this doesn’t refer to the same thing.
  53. 53. Execution Context Use apply, call or bind to change execution context.
  54. 54. Execution Context Usage: doSomething.apply(context, args); doSomething.call(context, arg1, arg2, ... argN); var doIt = doSomething.bind(context, arg1, arg2, … argN);
  55. 55. Execution Context Let’s bootstrap our earlier Ajax example to demonstrate.
  56. 56. Execution Context Ajax event handler assignment from earlier: var xhr = new XMLHttpRequest(); xhr.onload = function () { console.log(this.responseText); } xhr.open('get', '/weather_data'); xhr.send();
  57. 57. Execution Context Bootstrap data rendered into the page: <script> var bootstrapData = { "responseText": { "weather": { "high": "35 ºC", "low": "24 ºC", "precipitation": "0%", "humidity": "78%", "wind": "13 km/h" } } }; </script>
  58. 58. Execution Context Start with refactoring our callback: function parseData () { console.log(this.responseText); } var xhr = new XMLHttpRequest(); xhr.onload = parseData; xhr.open('get', '/weather_data'); xhr.send();
  59. 59. Execution Context Set Ajax code to poll every 15 seconds: function parseData () {console.log(this.responseText);} var xhr = new XMLHttpRequest(); xhr.onload = parseData; setInterval(function () { xhr.open('get', '/weather_data'); xhr.send(); }, 15000);
  60. 60. Execution Context bootstrapData is a global variable: <script> var bootstrapData = { "responseText": { "weather": { "high": "35 ºC", "low": "24 ºC", "precipitation": "0%", "humidity": "78%", "wind": "13 km/h" } } }; </script>
  61. 61. Execution Context Parse bootstrap data immediately on page load: function parseData () { console.log(this.responseText); } parseData.call(bootstrapData);
  62. 62. Prototypal Inheritance
  63. 63. Prototypal Inheritance “All objects in JavaScript are descended from Object” var myObject = new Object(); Object myObject
  64. 64. Prototypal Inheritance “All objects in JavaScript are descended from Object” Object.prototype.hello = 'world'; var myObject = new Object(); Object .hello myObject .hello
  65. 65. Prototypal Inheritance In JavaScript, functions can act like objects.
  66. 66. Prototypal Inheritance They have a prototype property allowing inheritance. function Person() {}; Person.prototype.name = "Bob";
  67. 67. Prototypal Inheritance You can create an instance of one using the new keyword: var person1 = new Person(); console.log(person1.name); // Bob
  68. 68. Prototypal Inheritance Live link with its parent: function Animal() {} var dog = new Animal(); Animal.prototype.speak = function (msg) { console.log(msg) };
  69. 69. Prototypal Inheritance Live link with its parent: function Animal() {} var dog = new Animal(); Animal.prototype.speak = function (msg) { console.log(msg) }; dog.speak('woof');
  70. 70. requestAnimationFrame, CSS transforms Optimization
  71. 71. Optimization Improving event handlers with delegation
  72. 72. Optimization Rather than assigning individual handlers: var a = document.getElementById('save'); a.onclick = function () { // save code };
  73. 73. Optimization Assign one for all of the same type: document.onclick = function (e) { e = e || event; var target = e.target || e.srcElement; if (target.id === 'save') { // save code } };
  74. 74. Optimization Improving animation
  75. 75. Optimization Improving animation setInterval(function () { someElement.style.left = (leftValue + 1) + "px"; }, 0);
  76. 76. Optimization Improve animation with requestAnimationFrame Key differences: •Animation stops when running in hidden tab •Browser optimized repaint/reflow
  77. 77. Optimization Animation stops when running in hidden tab •Uses less GPU/CPU •Uses less memory Translation = longer battery life
  78. 78. Optimization Browser optimized repaint/reflow Changes to CSS and the DOM cause parts or all of the document to be recalculated.
  79. 79. Optimization Source: https://developer.mozilla.org/en/docs/Web/API/window.requestAnimationFrame requestAnimationFrame compatibility
  80. 80. Optimization Source: https://developer.mozilla.org/en/docs/Web/API/window.requestAnimationFrame requestAnimationFrame compatibility
  81. 81. Security
  82. 82. Security Avoid eval
  83. 83. Security Use literals [] instead of new Array() {} instead of new Object()
  84. 84. Security Use literals Array = function () { // I am pretending to be an array. // I am doing something evil with your data. }
  85. 85. Security External scripts make your application insecure.
  86. 86. Thank you! Happy to answer your questions throughout the conference and afterwards! ara.pehlivanian@gmail.com twitter.com/ara_p

×