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

JavaScript Patterns chapter 8 of mine

JavaScript Patterns chapter 8 of mine

My presentation part of JavaScript Patterns chapter 8

Chein-Wei Huang

February 23, 2016
Tweet

More Decks by Chein-Wei Huang

Other Decks in Programming

Transcript

  1. Outline • Separation of Concerns • DOM Scripting • Events

    • Long-Running Scripts • Remote Scripting • Deploying JavaScript • Loading Strategies • Summary 2
  2. Separation of Concerns • Test without CSS/JS • No inline

    event handlers or style(?) ◦ ReactJS JSX: <button onClick={this.test(this)}>Submit</button> • Semantically HTML elements 4
  3. Capability Detection Check function exist instead of check browser agent

    // antipattern if (navigator.userAgent.indexOf('MSIE') !== −1) { document.attachEvent('onclick', console.log); } // better if (document.attachEvent) { document.attachEvent('onclick', console.log); } // or even more specific if (typeof document.attachEvent !== "undefined") { document.attachEvent('onclick', console.log); } 5
  4. DOM Access • Avoiding DOM access in loops • Assigning

    DOM references to local variables and working with the locals • Using selectors API where available • Caching the length when iterating over HTML collections (see Chapter 2) 7
  5. Avoiding DOM access in loops // antipattern for (var i

    = 0; i < 100; i += 1) { document.getElementById("result").innerHTML += i + ", "; } // better - update a local variable var i, content = ""; for (i = 0; i < 100; i += 1) { content += i + ","; } document.getElementById("result").innerHTML += content; 8
  6. Assigning DOM references to local variables and working with the

    locals // antipattern var padding = document.getElementById("result").style.padding, margin = document.getElementById("result").style.margin; // better var style = document.getElementById("result").style, padding = style.padding, margin = style.margin; 9
  7. Using selectors API where available document.querySelector("ul .selected"); document.querySelectorAll("#widget .class"); https://developer.mozilla.org/zh-TW/docs/Web/API/document.querySelector

    • Faster than jQuery Dom method • document.getElementById(myid) is still the fatest • https://jsperf.com/getelementbyid-vs-queryselector/25 10
  8. DOM Manipulation(Document Fragment) // antipattern // appending nodes as they

    are created var p, t; p = document.createElement('p'); document.body.appendChild(p); p = document.createElement('p'); document.body.appendChild(p); 11
  9. DOM Manipulation(Document Fragment) var p, t, frag; frag = document.createDocumentFragment();

    p = document.createElement('p'); frag.appendChild(p); p = document.createElement('p'); frag.appendChild(p); document.body.appendChild(frag); https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment 12
  10. DOM Manipulation(Document Fragment) var oldnode = document.getElementById('result'), clone = oldnode.cloneNode(true);

    // cloneNode(true) if the children of the node should also be cloned, or false to clone only the specified node. https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode // work with the clone... // when you're done: oldnode.parentNode.replaceChild(clone, oldnode); 13
  11. Event Delegation • Bind event to parent instead of child

    • Use event.target to check the target node • Pros ◦ reduce event listeners • Cons ◦ hard to find the event listener from browser developer tool • Demo ◦ http://codepen.io/anon/pen/vLqvaV 16
  12. Event Delegation • ReactJS JSX: <button onClick={this.test(this)}>Submit</button> ◦ React use

    single top level event listener ◦ https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood- autobinding-and-event-delegation 17
  13. Long-Running Scripts (setTimeout) var timer1 = setTimeout(myfunction1, 50); var timer2

    = setTimeout(myfunction2, 100); var timer3 = setTimeout(myfunction3, 150); 18
  14. Long-Running Scripts (Web Wrokers) var ww = new Worker('my_web_worker.js'); ww.

    onmessage = function (event) { document.body.innerHTML += "<p>message from the background thread: " + event.data + "</p>"; }; // Output message from the background thread: hello there message from the background thread: halfway there, `tmp` is now 3749999975000001 message from the background thread: all done 19 // my_web_worker.js var end = 1e8, tmp = 1; postMessage('hello there'); while (end) { end -= 1; tmp += end; if (end === 5e7) { // 5e7 is the half of 1e8 postMessage('halfway there, `tmp` is now ' + tmp); } } postMessage('all done');
  15. XMLHttpRequest var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function ()

    { if (xhr.readyState !== 4) { // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState return false; } if (xhr.status !== 200) { alert("Error, status code: " + xhr.status); return false; } document.body.innerHTML += "<pre>" + xhr.responseText + "<\/pre>"; }; xhr.open("GET", "page.html", true); xhr.send(""); 21
  16. JSONP • Not restricted by the same-domain policy (Use script

    tag) • Often JSON wrapped in a function call • https://zh.wikipedia.org/wiki/JSONP var script = document.createElement("script"); script.src = “http://remote.org/getdata.php?callback=myHandler”; document.body.appendChild(script); // Output of http://example.org/getdata.php?callback=myHandler myHandler({“hello”: “world”}); 22