JavaScript Performance Tips
Posted: September 5, 2013 Filed under: Uncategorized Leave a commentavoid loops
avoid unused code
avoid loging
using strict mode
use === instead of == (browser has more clarity)
exploit hoisting
use hasOwnProperty
use local references for values that have deeper resolution path
avoid synchronous calls
minimize dom updates
minimize style updates
use fragment whenever applicable
avoid (for i in) on objects
exploit power of mapping
have a check on prototypal inheritance
Story of DataTable
Posted: April 7, 2013 Filed under: Uncategorized | Tags: backbone, canjs, datatable, javascript, yui3 Leave a commentMany times I had chance to work on DataTable which in fact most complicated widget you can think of. Every time my preference of stack were depending on the company and team. In all I had opportunity for
1. Extending existing DataTable in YUI3 and adding Sorting/Pagination/Filter/Scrolling functionalities using extensions and plugins
2. Created a DataTable component using Backbone which had futures like Sorting and Filter
3. Created a DataTable component using CanJS which was heavily using EJS template with live binding.
4. Again working DataTable component using Backbone with different approach, planning to have all possible features to it.
While working on these stack, I figured out that DataTable component has it’s own unique challenges, and implementing features like sorting, pagination, filters, on-demand dataloading, scrolling, inline edits, expandable detail views etc will increase depth and breadth of your JavaScript knowledge. Here I am listing challenges I faced and how did I encounter them.
Normally below are the features expected in DataTable
1. Pagination with rows per page drop-down, with first, last, next, previous page links, go-to box, linked page numbers
2. Sorting, most probably single column sorting
3. Filters, table level filter or column level filter
4. In-Line edit for certain columns
5. Column formatters, currency, date, number and link formats
6. Show/Hide columns
7. Scrolling, horizontal scrolling with pagination or vertical scrolling without pagination
8. Expandable Detail Views
9. On-Demand data-loading
…more to come
Rooted Tree implementation in JavaScript
Posted: January 7, 2013 Filed under: Uncategorized | Tags: datastructure, datastructure rooted tree, javascript, root tree, rooted, tree, tree implementation Leave a commentHere is an example of Rooted Tree implementation;
var TreeNode = function TreeNode (data, parent) { this.data = data; this.parent = parent; } TreeNode.prototype.preOrder = function(){ this.visit(); if(this.firstChild){ this.firstChild.preOrder(); } if(this.nextSibling){ this.nextSibling.preOrder(); } } TreeNode.prototype.postOrder = function(){ if(this.firstChild){ this.firstChild.postOrder(); } this.visit(); if(this.nextSibling){ this.nextSibling.postOrder(); } } TreeNode.prototype.getLastSibling = function() { if(this.nextSibling){ return this.nextSibling.getLastSibling(); }else{ return this; } }; TreeNode.prototype.visit = function(){ console.log(this.getData()); } TreeNode.prototype.getData = function() { if(this.parent){ return this.parent.getData()+'-'+this.data; }else{ return this.data; } }; var Tree = function Tree (root) { this.size = 0; this.root = root; } Tree.prototype.addNode = function(node, parent) { if(!parent){ parent = this.root; } node.parent = parent; if(!parent.firstChild){ parent.firstChild = node; }else{ parent.firstChild.getLastSibling().nextSibling = node; } tree.size++; };
Usage
var treeHeight = 8; var root = new TreeNode('root', null); var tree = new Tree(root); for(var i=0; i<treeHeight;i++){ var node = new TreeNode(i+''); for(var j=0; j<i;j++){ var node2 = new TreeNode(i+''+j); tree.addNode(node2, node) for(var k=0; k<j; k++){ tree.addNode(new TreeNode(i+''+j+''+k), node2) } } tree.addNode(node); } root.preOrder(); root.postOrder();
Coding guidelines for JavaScript Starters
Posted: November 27, 2012 Filed under: Uncategorized Leave a commentIt’s not a complete list, I am just listing stuff that I thought overlooked.
1. Keep the code readabble, Indent well, try using some editor which supports auto-indent.
2. Keep function/method names descriptive. Don’t try to save bytes here, if it is a handler call out what that handler handles. Saving bytes can be easily done in minification, you don’t have to do that while writing code.
3. JSHint/JSLint your JS code before commiting to git, most probably your code will get concatinated with other JS files in near future, JSHint/Lint will make sure your code live well with others’. There are some editors which support “check as you type”.
4. Comment as much as possible. We are yet to agree on a company wide JS documentation tool/standard, but commenting now will help us when we agree and adopt one. It will also help you to remember reasons behind design decisions when you come back later.
5. When concluding on the solutions, always ask “Does it scale?”. We are moving towards SPAs every where and whole applications will get rendered/managed in single page, if your solution doesn’t scale there is no point in having it.
6. Keep model and view seperate, If we are using Backbone, CanJS or any MV* framework, we choose it for a reason,that is keeping model and view separate. Thumb rule is, interaction on one dom element should not update another dom element directly, flow should be dom-element1=>model and then model=>dom-element2
7. Keep your methods/functions small, if you have to write more than 2 lines to describe what that function does, that’s an indication that one function needs some splitting.
8. Adopt DRY as much you can, if you are copy pasting between modules, there is some thing wrong in you approach.
9. Add Event listeners only when needed. make sure you remove all listeners you added
10. When passing more than 1 arguments, pass it as argument object, this will let you scale function easily, also it’s easy to write fallback for missing argument
11. If widgets/components have dependency for data, make sure you handle loading state, letting user know that data is being loaded is very important
12. If you are combing dom elements to read the state of a widget, this could become slow as your application scale, always maintain a Model, whenever data needed out of widget, read it from Model, while updating update both model and view.
13. Minimize DOM queries, use local variables whenever you make same query multiple times.
14. Keep an eye on what is getting added to global namespace, lesser is better here.
Finally if you have not yet read “JavaScript Good Parts (from Douglas Crockford)”, get a copy right away, and read it once. You should be able to finish that in couple of hours, but it will save loads of debugging time for you in future. If you are coding JS you should know what you should not do, and this book just tell you that.
JavaScript to generate lorem ipsum data
Posted: September 30, 2012 Filed under: Uncategorized Leave a commentvar lorem = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"; var loremArray = lorem.split(/s/); function getWordlist(count, wordcount) { var toreturn = [] var loremlength = loremArray.length wordcount = wordcount || 1; for (var i = 0; i < count; i++) { var s = [] for (var j = 0; j < wordcount; j++) { s.push(loremArray[Math.ceil(Math.random() * loremlength)]); } toreturn.push(s.join(' ')); } return toreturn; } function logArray(arr) { for (var i = 0, l = arr.length; i < l; i++) { console.log(arr[i]); } } logArray(getWordlist(10, 3)) logArray(getWordlist(10, 1))
Mixin Pattern
Posted: September 30, 2012 Filed under: Uncategorized | Tags: javascript, mixin, pattern Leave a commentvar Selectable = function () {}; Selectable.prototype = { isSelected: function () { return this.selected || false; }, setSelected: function (boolean) { this.selected = boolean; }, toggleSelected: function () { this.selected = !this.isSelected() } } function augment(givingClass, receivingClass) { // if copying selected properties var methodOrProperty; if (arguments[2]) { for (var i = 0, len = arguments[2].length; i & lt; len; i++) { methodOrProperty = arguments[2][i]; receivingClass.prototype[methodOrProperty] = givingClass.prototype[methodOrProperty] } } else { //copy all properties for (methodOrProperty in givingClass.prototype) { if (!receivingClass[methodOrProperty]) { receivingClass.prototype[methodOrProperty] = givingClass.prototype[methodOrProperty] } } } } var ListItem = function () { this.selected = false; } augment(Selectable, ListItem); var item1 = new ListItem(); console.log(item1.isSelected()); //false
Observer pattern implemented in vanilla JavaScript
Posted: September 29, 2012 Filed under: Uncategorized | Tags: event, javascript, vanilla Leave a commentEver wondered how custom events works in JavaScript, it’s a very simple implementation of Observer pattern, here is a raw example written in vanilla JavaScript, popular libraries like Jquery and YUI3 has more polished implementations where you can unsubscribe without tokens, by functions/event names, but at heart this is what happens in background.
var Observer = {}; (function (ob) { var subscribeToken = -1; var subscriberIndex = {} ob.publish = function () { //type of event is the first argument var type = arguments[0] //rest of arguments will be used as arguments for handler execution var args = [].slice.call(arguments, 1) if (!subscriberIndex[type]) { return false; } var subscribers = subscriberIndex[type]; var len = subscribers ? subscribers.length : 0; while (len--) { subscribers[len].func(type, args) } //console.log(type, args) } ob.subscribe = function (type, handler) { if (!subscriberIndex[type]) { subscriberIndex[type] = [] } var token = (++subscribeToken).toString() subscriberIndex[type].push({ func:handler, token:token }) return token; } ob.unsubscribe = function (token) { for (var type in subscriberIndex) { var subscribers = subscriberIndex[type]; for (var i = 0; i < subscribers.length; i++) { var subscriber = subscribers[i]; if (token === subscriber.token) { subscribers.splice(i, 1) return token; } } } return this; } })(Observer) var token = Observer.subscribe('test', console.log) Observer.publish('test', {test:'test'}) //test [Object { test= "test" } ] Observer.unsubscribe(token) Observer.publish('test', {test:'test'}) // nothing happens
Singleton Creation pattern example
Posted: September 29, 2012 Filed under: Uncategorized | Tags: class, javascript, singleton Leave a commentNotes:
- Singleton is immediately executed function
var log = console.log; var Singleton = (function (){ var instance; var init = function (){ var privateVar = 'this is secret'; var privateMethod = function (){ return privateVar; } return { publicMethod : function (){ return privateMethod(); }, publicVar : 'this is public' } } return { getInstance : function (){ if(!instance){ instance = init(); } return instance; } } })() var singletonInstance = Singleton.getInstance() log(singletonInstance.publicMethod()) // this is secret log(singletonInstance.publicVar) // this is public log(singletonInstance.privateMethod()) //Error
Simple example illustrating private and public properties for JavaScript class
Posted: September 29, 2012 Filed under: Uncategorized | Tags: class, javascript, private, public Leave a commentvar log = console.log; var Class = function (){</pre> var privateVar = 'this is secrete'; var privateMethod = function (){ return privateVar; } return { publicMethod: function (){ return privateMethod() }, publicVar :'this is public' } } var instance = new Class() log(instance.publicMethod()) // this is secret log(instance.publicVar) // this is public log(instance.privateMethod()) //Error
Recent Comments