Web Optimization Summit: Coding for Performance

Post on 09-Jul-2015

1868 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

I discuss topics like method forking, lazy defining of methods, JS minifiers, dos and don'ts of minification.

Transcript

Coding for Performance

Parental Advisory : Hardcore Forking Action

By John-David Dalton

@jdalton ▪ john@fusejs.com ▪ http://allyoucanleet.com

function times(iterator, context) { $R(0, this, true).each(iterator, context); return this;}

Reduce Abstraction

1.

function times(iterator, context) { var i = -1, length = this; while (++i < length) iterator.call(context, i, i); return length;}

Reduce Abstraction

2.

function times(iterator, context) { var i = -1, length = this; if (context) { while (++i < length) iterator.call(context, i, i); } else { while (++i < length) iterator(i, i); } return length;}

Reduce Abstraction

3.

Test Before Tapping Dat

•Feature Testing (Awesomest)

•Feature Detection (Pretty good)

•Weak Object Inference (Almost as bad as UA sniffing)

•User Agent Sniffing (Just say no!)

4.

// true for Gecko and Webkitif ([ ][‘__proto__‘] === Array.prototype && { }['__proto__‘] === Object.prototype) { // test if it's writable and restorable var result, list = [], backup = list['__proto__']; list['__proto__'] = { }; result = typeof list.push === 'undefined'; list['__proto__'] = backup; return result && typeof list.push === 'function';}

Feature Testing

5.

// Host objects can return type values that are different from their actual// data type. The objects we are concerned with usually return non-primitive// types of object, function, or unknown.// For example:// typeof document.createElement('div').offsetParent -> unknown// typeof document.createElement -> object// typeof Image.create -> stringisHostType = (function() { var NON_HOST_TYPES = { 'boolean': 1, 'number': 1, 'string': 1, 'undefined': 1 }; return function(object, property) { var type = typeof object[property]; return type === 'object' ? !!object[property] : !NON_HOST_TYPES[type]; };})();

Feature Detection

6.

// true for IEreturn isHostType(window, 'ActiveXObject');

Feature Detection

7.

var xhr;

// Assumed to be IEIf (document.fileSize) { xhr = new ActiveXObject('Microsoft.XMLHTTP');} else { xhr = new XMLHttpRequest();}

Weak Object Inference

8.

function contains(element, descendant) { if (element.compareDocumentPosition) { return (descendant .compareDocumentPosition(element) & 8) === 8; } if (element.contains) { return element !== descendant && element.contains(element); } while (descendant = descendant.parentNode) { if (descendant == element) return true; } return false;}

Fork like Rabbits

9.

var contains = function(element, descendant) { while (descendant = descendant.parentNode) { if (descendant === element) return true; } return false;};if (isHostType(docEl, 'compareDocumentPosition')) { contains = function(element, descendant) { /* DOCUMENT_POSITION_CONTAINS = 0x08 */ return (descendant .compareDocumentPosition(element) & 8) === 8; };}else if (isHostType(docEl, 'contains')) { contains = function(element, descendant) { return element !== descendant && element.contains(descendant); };}

Fork like Robots

10.

var contains = function(element, descendant) { while (descendant = descendant.parentNode) { if (descendant === element) return true; } return false;};

if (isHostType(docEl, 'compareDocumentPosition')) { contains = function(element, descendant) { /* DOCUMENT_POSITION_CONTAINS = 0x08 */ return (descendant .compareDocumentPosition(element) & 8) === 8; };}else if (isHostType(docEl, 'contains')) { contains = function(element, descendant) { return element !== descendant && element.contains(descendant); };}

Fork like Hobbits

11.

var contains = function(element, descendant) { while (descendant = descendant.parentNode) { if (descendant === element) return true; } return false;};

if (isHostObject(docEl, 'compareDocumentPosition')) { contains = function(element, descendant) { /* DOCUMENT_POSITION_CONTAINS = 0x08 */ return (descendant .compareDocumentPosition(element) & 8) === 8; };}

else if (isHostType(docEl, 'contains')) { contains = function(element, descendant) { return element !== descendant && element.contains(descendant); };}

But don't fork Marsellus Wallace !

12.

plugin.getRelatedTarget = function getRelatedTarget() {

var setRelatedTarget = function(object, value) { object.getRelatedTarget = createGetter('getRelatedTarget', value); return value; },

getRelatedTarget = function getRelatedTarget() { var node = this.raw && this.raw.relatedTarget; return setRelatedTarget(this, node && fromElement(node)); };

// fired events have no raw if (!this.raw) { return setRelatedTarget(this, null); } // for IE if (typeof this.raw.relatedTarget === 'undefined’) { getRelatedTarget = function getRelatedTarget() { var node = null, event = this.raw; switch (event && event.type) { case 'mouseover': node = fromElement(event.fromElement); case 'mouseout': node = fromElement(event.toElement); } return setRelatedTarget(this, node); }; } plugin.getRelatedTarget = getRelatedTarget; return this.getRelatedTarget();

};

Forking + Lazy Load

13.

plugin.getRelatedTarget = function getRelatedTarget() {

var setRelatedTarget = function(object, value) { object.getRelatedTarget = createGetter('getRelatedTarget', value); return value; }, getRelatedTarget = function getRelatedTarget() { var node = this.raw && this.raw.relatedTarget; return setRelatedTarget(this, node && fromElement(node)); };

// fired events have no raw if (!this.raw) { return setRelatedTarget(this, null); } // for IE if (typeof this.raw.relatedTarget === 'undefined') { getRelatedTarget = function getRelatedTarget() { var node = null, event = this.raw; switch (event && event.type) { case 'mouseover': node = fromElement(event.fromElement); case 'mouseout': node = fromElement(event.toElement); } return setRelatedTarget(this, node); }; }

Forking + Lazy Load

14.

plugin.getRelatedTarget = function getRelatedTarget() { var setRelatedTarget = function(object, value) { object.getRelatedTarget = createGetter('getRelatedTarget', value); return value; },

getRelatedTarget = function getRelatedTarget() { var node = this.raw && this.raw.relatedTarget; return setRelatedTarget(this, node && fromElement(node)); }; // fired events have no raw if (!this.raw) { return setRelatedTarget(this, null); } // for IE if (typeof this.raw.relatedTarget === 'undefined') { getRelatedTarget = function getRelatedTarget() { var node = null, event = this.raw; switch (event && event.type) { case 'mouseover': node = fromElement(event.fromElement); case 'mouseout': node = fromElement(event.toElement); } return setRelatedTarget(this, node); }; }

Forking + Lazy Load

15.

getRelatedTarget = function getRelatedTarget() { var node = this.raw && this.raw.relatedTarget; return setRelatedTarget(this, node && fromElement(node)); };

// fired events have no raw if (!this.raw) { return setRelatedTarget(this, null); } // for IE

if (typeof this.raw.relatedTarget === 'undefined') { getRelatedTarget = function getRelatedTarget() { var node = null, event = this.raw; switch (event && event.type) { case 'mouseover': node = fromElement(event.fromElement); case 'mouseout': node = fromElement(event.toElement); } return setRelatedTarget(this, node); }; } plugin.getRelatedTarget = getRelatedTarget;

Forking + Lazy Load

16.

plugin.getRelatedTarget = function getRelatedTarget() { var setRelatedTarget = function(object, value) { object.getRelatedTarget = createGetter('getRelatedTarget', value); return value; },

getRelatedTarget = function getRelatedTarget() { var node = this.raw && this.raw.relatedTarget; return setRelatedTarget(this, node && fromElement(node)); };

// fired events have no raw if (!this.raw) { return setRelatedTarget(this, null); } // for IE if (typeof this.raw.relatedTarget === 'undefined’) { getRelatedTarget = function getRelatedTarget() { var node = null, event = this.raw; switch (event && event.type) { case 'mouseover': node = fromElement(event.fromElement); case 'mouseout': node = fromElement(event.toElement); } return setRelatedTarget(this, node); }; }

plugin.getRelatedTarget = getRelatedTarget; return this.getRelatedTarget();};

Forking + Lazy Load

17.

var cache = { }, reHyphenated = /-([a-z])/gi, uid = +new Date;

function toUpperCase(match, letter) { return letter.toUpperCase();}

function camelCase(string) { var key = uid + string; return cache[key] || (cache[key] = string.replace(reHyphenated, toUpperCase));}

Memoize

18.

Nay Context

// Prototype$$(‘.foo’);

// jQuery$(‘.foo’);

19.

Yay Context

// Prototypevar panel = $(‘panel’);panel.select(‘.foo’);

// jQueryvar panel = $(‘#panel’);panel.find(‘.foo’);

20.

Event Delegation != Magic

// Prototype usage$(‘myTable’).observe(‘click’, function(event) { if (event.findElement(‘td’)) { // do stuff }});

21.

Minifiers

•Packer 3.1 (Old School, You’re my boy, Blue!)

•YUI Compressor (Been around the block)

•Closure Compiler (Googtastic)

•JSMin (Ported to lots of languages)

22.

What’s Cool

// code like thisemit(‘I will be ’ + ‘concated by ‘ + ‘pirate magic’);

// will be valmorphanize intoemit(‘I will be concated by pirate magic’);

23.

Do

•Repeat use of the same variable names

•Store namespaced objects in variables

•Use variable lists

•Avoid compiled functions

24.

Do Not

•Become anal about semi-colons

•Replace all property names with variables

•Use short non-descriptive variable names

•Tug on Superman’s cape

25.

Links

http://github.com/jdalton/fusejs

http://developer.yahoo.com/yui/compressor/

http://code.google.com/closure/compiler/

http://www.crockford.com/javascript/jsmin.html

http://github.com/rgrove/jsmin-php/

http://base2.googlecode.com/svn/trunk/src/apps/packer/packer.html

http://code.google.com/p/base2/source/browse/#svn/trunk/src/apps/packer

Twitter: @jdalton @fusejs

Email: john@fusejs.com

top related