You are on page 1of 26

WEB OPTIMIZATIONS

Java Script and DOM


Unobtrusive JavaScript
• Just as you use CSS to separate style from content, you can also (to some degree) separate
JavaScript from your document.
• This is known as unobtrusive JavaScript.
• Revisiting the event delegation example, rather than adding the event handler to the element in
the markup, you can use addEventListener and an anonymous function for a more aesthetically
pleasing solution:

• <ul id='ourlist'>

• <li id="item1">Item 1</li>

• <li id="item2">Item 2</li>

• …….

• </ul>
Memory Management
• With the rise of JavaScript-heavy web applications, things have
changed.
• It’s quite feasible that the user may spend his or her entire session just
on one page, with Ajax being used to communicate with the server.
• As a result, inefficient memory usage has the opportunity to mount up
into something more significant.
• JavaScript uses the garbage collection methodology for managing
memory.
• Memory is allocated to objects and reclaimed by the garbage-
collection process when the object is no longer being used.
• Let’s look at an example using one of the most common sources of
such circular references:
Language Constructs

• it’s generally DOM manipulation that is slow, rather than JavaScript itself.
• Nevertheless, there are situations in which JavaScript can perform poorly.
• Let’s look at the common cases.
• Loops
for (var x=0; x < myarray.length; x++) {
...}
• You can improve the situation dramatically by fetching the size of the
array outside of the loop,
var count = myarray.length;
for (var x=0; x < count; x++) {
...}
var count = myarray.length;
for (var x=count; x--;) {
...}

• Your loop might look something like this:


for (var x=0; x < document.getElementsByTagName("span").length; x++){
... }
• Surprisingly, the following code is also affected:
for (var x=0, elements = document.getElementsByTagName("spans"); x <
elements.length; x++)
{
...
}
• Consider the following example, which converts between the Celsius and Fahrenheit temperature scales:
for (x=0; x <1000; x++)
{
var Fahrenheit = convertCF(x);
// now do something with Fahrenheit
}
function convertCF(x)
{
return x*1.8+32;
}
• To cut the overhead of calling convertCF, you can rewrite the loop like so
for (x=0; x <1000; x++)
{
var Fahrenheit = x*1.8+32;
// now do something with Fahrenheit
}
Variable Scope
• JavaScript uses the concept of local and global variables.
• Local variables exist only inside the function in which they are defined; global
variables are accessible from anywhere.
• Consider the following example:
var x = 1;
function foo()
{
var y = 2;
alert (x); // x has global scope, so this displays "1"
alert(y); // displays "2"
}
• Using global variables inside functions comes at a cost, though.
• JavaScript uses lexical scoping.
• Consider the following code:
var a = 1;
function bar()
{
var b = 2;
function baz()
{
var c = 3;
}
}
• One way to get around the use of globals inside of a function is to
pass the variables that you need as function parameters:
var x = 1;
function foo(z)
{
alert(z); // local variable, with value of 1
}
foo(x);
• The following example causes the global x to be looked up twice:
var x = 1;
function foo()
{
var y,z; y = x 2;
z = x 3;
}
foo();
• The following example results in only one global lookup of x:
var x = 1;
function foo() {
var y,z;
var tmp = x;
y = tmp 2;
z = tmp 3;
}
foo();
• eval():

• eval() suffers from a bad reputation in JavaScript for a number of


reasons.

• The reason for the poor performance of eval() is that browsers typically
did not cache the compiled code.

• If the contents of the eval() statement are dynamic, there is no


opportunity for caching.
• Regular Expressions
• Regular expressions (regexes) are an important part of most high-level
programming languages.
• JavaScript is no different, and the tips presented here are mostly
equally valid for other languages, too.
• However, think before you use a regex. Is it actually needed?
• Try to use ^ or $ to anchor the pattern being matched.
• Modifiers
• Regex modifiers are used to alter the meaning of the pattern being
matched.
• In JavaScript, the two most common modifiers are i (match case
insensitive) and g (global, don’t stop after the first match found).
• Reusing Expressions:
• The following example shows one of the most common ways of using regexes in
JavaScript:
for (var x = 0; x < array.length; x++)
{ var matches array[x].match(patterntomatch)
if (matches.length > 0)
{ // we've got a match
}
}
• The problem here is that JavaScript must internally parse and compile the regex, and this
happens for each iteration of the loop.
var myregex = patterntomatch
for (var x = 0; x < array.length; x++) {
if (myregex.test(...)(array[x])
{ // we've got a match } }
Loading JavaScript
• Consider the following code:
<img src="paypalcards.jpg">
<script type="text/javascript" src="test.js"></script>
<img src="forum.jpg">
• Following shows the waterfall view when this page loads in IE 8.
• Let’s rewrite the test page a little to see what happens:
• <img src="paypalcards.jpg">
• <img src="forum.jpg">
• <script type="test/javascript" src="test.js"></script>
• Following figure shows the waterfall view:
Nonblocking of JavaScript Downloads
• There are a few methods to create the nonblocking of the download
of JavaScript. Let’s take a closer look
• defer Attribute:
• The defer attribute is an IE extension that has found its way into
Firefox (starting with v3.5), Safari (v5), and Google Chrome (v7). The
syntax is as follows:
• <script type="text/javascript" defer src="test.js"></script>
• async:
• In HTML 5, you can use the async attribute to ask the browser to
download the script without blocking other downloads:
• <script type="text/javascript" async src="test.js"></script>
• Iframes
• Another method is to load the script inside an iframe like so:
• <iframe src="loader.html"></iframe>

• Dynamically Writing Script Tags:


• Probably the most popular method to invoke the nonblocking of the download
of JavaScript is to dynamically write the script tag with JavaScript.
var newjs = document.createElement('script');
newjs.src = 'test.js';
var head = document.getElementsByTagName('head')[0];
head.appendChild(newjs);
Merging, Splitting, and Inlining
• Web designers are often particular about their code and enjoy nothing
more than separating different JavaScript functionality into different
files.
• Thus, inside the <head> of a document, it’s common to see half a dozen
or more <script> tags loading external files, some with only a small
amount of code in them.
• Merging:
• There’s no question that storing scripts separately is the best way to
maintain a big project.
• But for a production website, it has an adverse effect on performance.
• The following figure shows the waterfall for a page with five small scripts in the
document head.

• shows a waterfall after merging the five scripts into a single file (combined.js).
As you can see, you save about 0.4 second by merging.
• The relevance of this test has also suffered from short-sightedness. It fails to
consider how the overall page loading time is affected. If you add four images
to the page, the waterfall view (again with IE8) looks as shown in figure
• In the following figure, the combined JavaScript file is used. Resource 3 is
fetched over the existing connection, but resources 4 and 5 each require a new
connection to be opened.
• The following figure shows the defer attribute is used to load the
combined JavaScript file.
• No blocking occurs, and three of the images are requested
immediately.
• the defer attribute is used on each of the four JavaScript resources.
• This leads to an increase in the amount of parallelization, but the effect is still
an increase in loading time.
• The combined version is approximately 1 second faster to complete.

You might also like