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.
2. I Am
Ankit Rastogi
a passionate Learner
Website : http://ankitrastogi.com
3. Stages of Learning
Shuhari - first learn, then detach, and
finally transcend
Shu - “Obey”
ha - “Detach”
ri - “Separate”
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();
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. 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. 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. 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. 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. 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. 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. 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. // 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. 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. 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. // 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
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. 2
var aGlobalVar = 1;
function doSomething(val) {
var i = 1000, agv = aGlobalVar;
while (i--) {
agv += val;
};
aGlobalVar = agv;
};
doSomething(10);
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. 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. 9
Lazy JS Parsing
Minimizing JavaScript parse time.
Increase performance especially in mobile.
<html>
...
<script id="lazy">
/*
JavaScript of lazy module
*/
</script>
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>
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. 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. 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. 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. 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
36. 2
function setupAlertTimeout() {
var msg = 'Message to alert';
window.setTimeout(function() {
alert(msg);
}, 100);
}
Identify the problem
37. 2
function setupAlertTimeout() {
window.setTimeout(function() {
var msg = 'Message to alert';
alert(msg);
}, 100);
}
Solution?
38. 2
function alertMsg() {
var msg = 'Message to alert';
alert(msg);
}
function setupAlertTimeout() {
window.setTimeout(alertMsg, 100);
}
Solution
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. 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. 2var divs = array( document.getElementsByTagName('div')
);
for (var i=0; i < divs.length; i++ ) {
var div = document.createElement("div");
document.appendChild(div);
}
Solution
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.