-->
1. Javascript File Loading
Load script basic:
Load file in header, middle
Load script dynamically:
Insert DOM Element:
By using dynamic js file
loading you can avoid the other files being blocked while the js file is
downloading, so maximize total number of js files can be requested at a time.
Ex:
ga.js without dynamic load
ga.js with dynamic load
In the first case, GA use: document.write(unescape("%3Cscript
src='" + gaJsHost + "google-analytics.com/ga.js'
type='text/javascript'%3E%3C/script%3E")); it blocks other request
until ga.js completely loaded.
In the dynamic loading case:
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-7345054-1']);
_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);
})();
The command being pushed in to queue until ga.js fully
loaded and create a DOM element with source pointed to ga.js destination.
The dynamic loading, there is only execution period is on browser UI Thread, so
it decrease the UI Blocking which cause other UI Thread have to wait. Notice
that in this case, code execution will be executed right before the next UI
Thread fired!
Defer
:
With defer tag, browser
wont execute script until every UI content updated successfully!
Cons: Compatible with
IE, the other one are not supported in older versions!
Script execution is fired at end, after UI updated.
Async :
Js file will be
downloaded and parsed immediately but will be executed when it is executable on
UI Thread, a little similar to dynamic loading!
Compress javascript file:
Before
After
2. Value
& Execute
Local,
global variables
Scope chain :
Keep in mind, try to limit the global variables as much as possible, in
scope chain JavaScript always put
global variables at end. So every executions, JavaScript engine have to spend
more effort and time to look for the global variables!
The local variables are always on the first scope! Also, global
variables are easy overwritten by accident.
Eg:
Global variable access
(function(){
n=0; m=0;
for(i=0;i<=9999;i++){
m=n+i;
}
})();
=> ~18ms
Local access, global cache
(function(){
var n=0, m=0;
for(var i=0;i<=9999;i++){
m=n+i;
}
})();
=> ~2ms
Scope chain map:
try/catch,
with agumentation:
Execute script with this method,
local
variable will be pushed into 2nd scope, try/catch or with agument will
be in the first scope, so accessing to the variables takes more time.
While executing script, JavaScript engine will search through scope chain to find
the object ‘name’, stat from the first scope, if nothing found it will continue
to search to the next scope until end. If there is no object found in the whole
scope then it will return undefined. Oh hey, reduce the
Object deep.
Loops (ECMA-262 – Chap 12-6)
for loop : 4 parts– Pretest,
condition, post-execute and loop body
while : 2 parts – Simple pretest
loop, prestest evaluated excuted and loop body followed.
do-while : 2 parts – Post-test loop,
loop body and post-test condition.
for-in :
Avoid to work with array by using for-in, the working process of this function
is it will go through all of the items and return the properties of the items
but not follow by the index.
for-in slowest!!!
Exam:
For-in
(function(){
var person={fname:"Ho",lname:"Ten",age:25}, cnt='';
for(var j=0;j<1000 br="" j="">
for (var z in person)
{
cnt += person[z] + j + '|';
}
}
})();1000>
=> ~1ms
for
(function(){
var person={fname:"Ho",lname:"Ten",age:25}, cnt='';
for(var j=0;j<1000 br="" j="">
for(var i=0;i<1 br="" i="">
cnt += person['fname'] + j + '|'
+ person['lname'] + '|' + person['age'] + '|';
}
}
})();1>1000>
=> ~1ms
3. DOM
DOM
access
HTML Collection is similar to array, it always updated so while being updated, DOM always re-painted/re-flow(read
below about this) after each execution.
So to reduce the access, execution time: Cache HTML Collection into local
variable (include length, items…)
Cache DOM in local variable.
Before:
(function(){
for(i=0;i<=1000;i++){
document.getElementById('toc__header').innerHTML='Table
of Contents ' +i;
}
})();
=>~85ms
After:
(function(){
var doc = document.getElementById('toc__header').innerHTML='Table of Contents
';
for(i=0;i<=1000;i++){
doc + i;
}
})();
=>~2ms
DOM
Element change:
Re-paint : When there is a style changed(Include background, color, border).
Re-flow : When there is a changed of structure, shape… Once re-flow event
triggered, JavaScript engine will have to work with all of the elements which
relate to the current one, it is highly chance that the first DOM element also
being affeted. SO – RE-FLOW IS REALLY SLOW.
Avoid?:
Remove element, update the change and insert into the previous position.
Set element to none, update the change and set it display back.
Use documentFragment to change the DOM
Element to reduce repain, reflow.
To change element’s style, just use the css and change the class name.
Long
running scripts:
This issue happens difference on each browsers.
On IE Javascript engine will warns the error depends on the total of executed
command, default is 5.000.000. JS Engine will stop execute script while
displaying the warn message, if you choose Yes, then the total of execution
script number will be reset.
On Firefox Javascript engine warn the error depends on total execution time of
the script, default is 10s. If Yes pressed, then total execution time will be
reset.
Chrome does not work with the two of above methods, it depends on OutOfMemory
event.
What may cause the Long running script issue:
- Working too much with DOM.
- Too much loop, or too much processes inside the loop.
- Too much recursion.
Reduce?:
- Split task, data smaller:
var arr = [ "item1", "item2",
"item3",…],
carr = arr.concat(); //clone the array
chunk(carr, function(item){
console. log(item);
});
- Use the setTimeout function to delay the script execution while process the
other one:
setTimeout(function(){
script to execute here…
}, 100);
Javascript
Memory Leaks:
Javascript has its Garbage Collector. Each object saved in memory and managed
by the collector (store, withdraw) depends on if it still relates to the other
objects or not. In some cases Garbage Collector lose its control, or the
related objecte(s) in ‘circular reference’ then memory leaks happens. This
issue is easy to happen when using with closure(inner) function to work with
Object, DOM, Mouse event, Page event.
Reduce? :
Try to reduce using closure.
Attach specific event
Set Null to the object once finished working on it.
Others stuff:
Object literal:
Classic: var arr=new Array; var obj = new Object;
Literal: var arr = []; var obj={};
Exam:
Classic way
for(var i=0;i<=999;i++){
var arr=new Array;
var obj=new Object;
}
=>~4.5ms
Literal
for(var i=0;i<=999;i++){
var arr=[];
var obj={};
}
=>~2.5ms
Try to get away with eval cause each
execution, JavaScript Engine will have to convert source code into executable
before executing it.
Use function name when using setTimeout or setInterval function, if the script
execute the function by passing the string, eg: ‘funcExam()’ then it becomes
similar like eval():
Before:
setTimeout(‘funcExam()’,100)
After:
setTimeout(funcExam,100)
Gzip : gzip scripts, stylesheets, XML, JSON (not images, PDF)
Minimum HTTP Request : To avoid blocking other resource requests, reduce UI
blocking. Reduce cookie, Cookie is not cache able and always fresh on both
client and server, so each cookie costs: Bandwidth, Computer/Server environment
such as memory, cpu...
HTTP Header cache
option: