Upload
phil-lanasa
View
218
Download
0
Embed Size (px)
Citation preview
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
1/35
JavaScript:Leverage it's strengths
to eliminate it's weaknesses
by P. LaNasa
http://www.sitekickr.com/
http://www.sitekickr.com/7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
2/35
Contents
1. Introduction
2. Fun with JavaScript Numbers and Prototype
3. Fun with JavaScript Strings and Prototype4. Drop and give me 20 units: enhancing the numeric
5. Assertions are possible
6. Caching function return values7. JavaScript organization for web development
8. Avoiding inline JavaScript
9. Using barricades for a more robust website10. Bonus: Ad optimization leveraging JavaScript to improve RPM
11. Bonus: Optimize your JavaScript, save the environment
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
3/35
1. Introduction
I've been developing websites for over 10 years now, dabbling in almost every language andtechnology available, but also narrowing in on a handful of those that I find myself using on a daily
basis. For many, that handful can be summed up in the popular acronym, LAMP (Linux, Apache,
MySQL, Python/PHP/Perl). But, over the years, you really start to develop your own acronym that best
describes your everyday development stack. For me, it's LAMCFJS (Linux, Apache, MySQL,ColdFusion, JavaScript). Of course, two of those don't fit the set, ColdFusion, because it requires a
commercial license, and JavaScript because it's client-side. But that's my stack, and I'm stickin' to it.
In recent years, I've developed a great fondness for JavaScript, and find myself blogging about it far
more than any other topic. So, I thought I'd give this ebook thing a try, and piece together a few
related posts. I hope you enjoy!
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
4/35
2. Fun with JavaScript Numbers and Prototype
One of the things that makes JavaScript so portable is it's intentionally minimal library of built-infunctions. By reducing the assumption that some off-the-wall function is available in a given version,
we are nearly guaranteed that our scripts will work in any environment.
However, this also means that a bit more work as to be done on the part of the developer to create basicfunctions that might otherwise be available in other languages. The good news is that the need for thesecommon functions has been lingering for many years, so most are readily available on the web.
This lack of built-ins brings rise to another powerful feature of the language though. Because it's
assumed that many functions will need to be created to operate on primitive data types, JavaScript
provides us with the prototype property on function objects. Prototype allows us to easily add newmethods to built-in objects (classes) "on-the-fly". Meaning, if you've already instantiated a numeric
variable, any method you add to the Number prototype will automatically, and instantly be applied.
So, let's have some fun with Number's prototype!
Is Number between x and y
This function isn't going to win any awards, but don't you think it looks cleaner than: if(x >= 5 &&
x = x && this.valueOf() x = 10;> x.between(5, 15);
true
Safe division (avoiding divide by zero issues)
I get the divide by zero problem, you can't divide anything into 0 parts, unless you're Chuck Norris.
But, as far as 90% my web apps are concerned, divide by zero isn't some cool abstract concept, they
just want a return value of zero (or maybe N/A).
But, instead, I need to perform checks every time I do a division operation, to make sure the result isn't"infinity", as returned by JavaScript when you divide by zero.
I'm not a fan of having dozens of useless conditions floating around my code. Instead, I'd like to add a
level of abstraction to the divide by zero concept, letting my code think that the result is always zero.Further, I'd like to encapsulate that into a function.
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
5/35
Number.prototype.safeDivideBy = function(x) {
var result = this.valueOf() / x;
if(result === Infinity) {return 0;
}
else {return result;}
}
> x = 10;
> x.safeDivideBy(0);
0
Convert to currency string
Your used to seeing currency related functions on the server-side, but with all this rich web application
developer going around, a good set of currency-related functions might come in handy. Here's a start!
Number.prototype.currency = function() {return '$' + (parseFloat(this.valueOf()).toFixed(2)).toString();
}
> x = 10> x.currency
"$10.00"
Random numbers
I can't actually recall ever needing a random number between 0 and 1, but that's what JavaScript's
random() function gives you. That's what any good random() function should give you. It's our job tobuild on that function for the specific needs of our application. In most cases, this means multiplying
the result by a number, then rounding to an integer. Not bad, but this could be encapsulated into a
function just as easily:
Number.prototype.randomMax = function() {// return a random number with a maximum value of xreturn Math.floor(Math.random() * (this.valueOf() + 1));
}
> x = 10> x.randomMax();
3
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
6/35
Existence in an array
If you've ever read "Code Complete" by Steve McConnell, you probably recall his discussion aboutProgrammingInto a Language. He was referring to the concept of tailoring a language to suit your
development needs, rather than adjusting your needs to fit the limitations of the language. Prototype isone way we can achieve this within JavaScript.
I used to do a fair amount of Python development, and came to love the in keyword syntax. It was soflexible in determining existence of one variable in a list or array. For example:
'test' in 'testing'
'test' in ['test', 'test1']
9 in [9, 10, 11]
I came to love it so much, that I just had to have it in my JavaScript development!
Number.prototype.in = function(array) {var arrayLength = array.length;for(var i=0; i < arrayLength; i++) {
if (array[i] === this.valueOf()) return true;}return false;
}
> myArray = [5,6,7,8]> x = 1
> x.in(myArray) false
> x = 7> x.in(myArray) true
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
7/35
3. Fun with JavaScript Strings and Prototype
More than a few reader's of my previous post on numbers pointed out that some of the functions Icreated were little more than semantically different from built-in functions. I agree, and that's okay.For
me, adding functions to a built-in object's prototype doesn't serve to create cutting-edge string
manipulation routines, but rather to reduce the complexity of my code, by encapsulating commonlyused algorithms into an easy-to-call function.
Using a built-in object's prototype not only allows us to use a more intuitive syntax:
newString = myString.awesomeFunction();
But also helps us to maintain functional cohesion within our objects. Meaning, we don't need toscramble a bunch of unrelated functions together into a giant utility class, i.e.
newString = util.awesomeFunction(myString);
Not only does this lengthen our code, but it's disorganized. A function that does string manipulation hasno business in a class (object) that calculates the perimeter of a rectangle.
Furthermore, it wouldn't make sense to create another class (object) to house string manipulationmethods when we already have the perfect one built in the String object.
So, let's have some fun with String's prototype!
Occurrences in a string
Sure, this one's easy. Just perform a RegEx match. But, to someone else reading your code, it might not
be immediately apparent what you're trying to do.
myString = 'this is my string';
numTimes = myString.match(/is/g).length;
Drop that into a function on String's prototype and you've got more readable code at the very least:
String.prototype.occurrences = function(substring) {var occRegEx = new RegExp(substring, 'g');return this.match(occRegEx).length;
}
> myString.occurrences('is'); 2
Okay, that was not awesome. Hey, I'm just getting started!
http://en.wikipedia.org/wiki/Cohesion_(computer_science)http://en.wikipedia.org/wiki/Cohesion_(computer_science)7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
8/35
Markup
How many times have you written or seen JavaScript like this, myself included:
if(document.form1.name.value === '') {document.write('Oh no, you forgot your name?');
}
All those gurus are always telling you to keep JavaScript out of your HTML, so shouldn't the reverseapply? But, I really want to just spit out a boldface message. Here's a cleaner way:
String.prototype.bold = function() {return '' + this + '';
}
document.write('Oh no, you forgot your name?'.bold());
Language
The previous couple functions walk the line of cohesion and usefulness, maybe even step over it. So,let's get back to the core of what a string is: typically a word or group of words in a given language.
The String prototype is the perfect home for language functions.
String.prototype.isQuestion = function() {var questionIdentifiers = ['when', 'where', 'why', 'what', 'who',
'how', 'can'];
// does the string contain a question mark?if(this.indexOf('?') !== -1) {
return true;
}// search keyword may indicate a question without explicitly
specifying the question markfor(var i = 0; i < questionIdentifiers.length; i++) {
if(this.indexOf(questionIdentifiers[i]) !== -1) {return true;
}}
return false;}
We could use our new function to refine a user's search by conditionally returning results more likely toanswer questions, than to provide generic information:
if(searchPhrase.isQuestion()){// favor search results in the knowledge base
}else {// favor search results in the product store
}
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
9/35
Is it a Word?
There's an unfair bias towards the numeric in computer science. Of course, it all stems from the factthat the CPU speaks numeric, while we humans speakstring. You can follow a gradual trend towards
natural language-based syntax in popular development languages such as ColdFusion and Python. But,
there really isn't much happening in terms of native support for natural language processing. I'm a littlesurprised by this, because I feel as if half of the applications that I develop require at least a very
primitive form of natural language processing (search, form validation, speech recognition, etc.)
Many languages offerisNumeric(), isDate(), or isArray() functions. But, how about
isWord(), isVerb(), isCommand()?
isCommand() could be used in searching algorithms (similar to isQuestion()) above. If a
command is detected, the user might know more or less what they are looking for, otherwise, they may
need a deeper level of assistance.
isWord() could be used in form validation. If a user submits a field, validate that it's actually a word
(or group of words). The definition of a word is subjective, but we'll make a few assumptions:
1. A word does not contain spaces
2. A word can contain only letters or the hyphen3. A word is less than 25 characters in length
String.prototype.isWord = function() {if(this.length > 25) {return false;
}return /^[A-Za-z\-]*$/.test(this);
}
A user submits a form which has fields for first and last name, so you validate against our new isWord()function:
if(!firstname.isWord()) {alert('Is that really your name?');
}
Well, maybe it isn't. Many folks out there have a two-word first name. So, let's expand our String
prototype to help out here:
String.prototype.words = function() {return this.split(' ');
}
Now we are armed with the basics necessary to properly validate a first name:
for each(item in firstname.words()) {if(!item.isWord()) {alert('Is that really your first name?');break;
}}
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
10/35
4. Drop and give me 20 units: enhancing the numeric
When your high school gym teacher asked you to "drop and give me 20", did you ever have the guts to
ask, "20 what?" Being the geeks that we are, such a question is perfectly valid, although in asking you
might just earn yourself another 20 units of unwanted exercise! Although assumptions can be made in
the real world about the unit implied by a certain context, the same can't be said for our code.Compilers and interpreters usually can't make assumptions like the one above based on context.
Every programming language supports numbers natively, although they are almost always implemented
as primitive types a place in memory to store a number, nothing less, nothing more. But as the
opening paragraph suggests, numbers by themselves present very little information, unless they arepaired with a unit. We write our own code to deal with units, but most often the code is not consistent,
both in checking the unit of a number, and converting to and from units.
If you are developing in a dynamic language, such as JavaScript, you are offered an opportunity to
enhance the way numbers are stored natively. The ability to "attach" a unit to a number can be gifted tothe Number data type. In the case of JavaScript, this is possible because a Number is an object, and
most objects can be modified through JavaScripts prototype language feature.
Enhancing the Number object with the prototype property:
Number.prototype.setUnit = function(unit) {this._unit = unit;
}
Number.prototype.getUnit = function() {return this.unit;
}
The downside is that to leverage these new functions, we need to "formally" create a number object:
myNum = new Number(56);myNum.setUnit('inches');console.log( myNum.getUnit() );
On the flip-side, we still get to use our number as we're used to, it's functionally the same:
myNum + 50 is still a valid arithmetic operation. The internal value of myNum is still 56.
Adjusting the constructor for more meaningful code
Sure, the technique above works great, but who really wants to initialize a Number object that wayevery time they want need to use an integer or float? What if we adjusted the Number object's
constructor, to allow us to provide the unit as well? That would certainly make our additional efforts of
creating a Number object more worthwhile, and perhaps make the code a little easier on the eyes:
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
11/35
var oldProto = Number.prototype;Number = function(num, unit) {this.value = num;this.unit = unit;
};oldProto.valueOf = function() { return this.value }Number.prototype = oldProto;
Number.prototype.setUnit = function(unit) {this.unit = unit;
}
Number.prototype.getUnit = function() {return this.unit;
}
The real magic of the code above is the recreation of the valueOf() function on the Number object. If
you've read an opinions on creating numbers with the new keyword, you might have found them all tobe against such a practice. But, much of their reasoning is that you loose the ability to perform
operations on them. By redefining the valueOf function that JavaScript uses internally, we preserve thatcapability.
However, it should be noted that the equality operation will no longer work! This is important toremember.
x = new Number(30, 'inches');y = new Number(30, 'inches');
x == ywill return false. This is because the equality operator does an object comparison and does
not use the valueOf() function. I'd have to say that this is probably the only downside to this method,
we're forced to compare against the valueOf() method:
x.valueOf() == y.valueOf();
Or, if we're feeling ambitious, adding a equals function to the Number object would serve our purposes
equally well:
x.equals(y);
If you think this approach lends to code that's easier to read and write, using the code examples above,
creating such a function should be relatively easy.
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
12/35
Avoiding inconsistent unit values
As in the examples above, we certainly could allow string literals to be passed into the constructor. But,what happens when we use inches in one case,Inches in another case, and inch in yet another case?
There are too many possible conditions to account for when testing against the units value. A simple
solution to this is to provide a basic "units map":
Number.units = { inches: 'in', millimeters: 'mi', feet: 'ft' }
So, our new method of creating a Number object would look something like:
x = new Number(30, Number.units.inches);
But, what would prevent supplying string literals to the constructor? You could also perform some
validation in the constructor:
Number = function(num, unit) {this.value = num;
var unitValidates = false;
for each(value in Number.units) {if(value === unit) {unitValidates = true;break;
}}
// an assertion would make more sense here// unless we're accepting unit input from the userif(!unitValidates) {throw new Error(unit + ' unit is not allowed');
return false;}
this.unit = unit;};
Dropping in the conversion functions
Next comes the need to convert between units. There are two ways we can do this:
Number.unitMap = [
{Number.units.inches :{Number.unit.millimeters: 25.4,Number.unit.feet: 1 / 12 },
{Number.units.millimeters:{Number.unit.inches: 1 / 25.4,Number.unit.feet: 1 / (25.4 * 12) },
{Number.units.feet:{Number.unit.inches: 12,Number.unit.millimeters: 12 * 25.4 }
]
https://www.sitekickr.com/blog/javascript-assertions/https://www.sitekickr.com/blog/javascript-assertions/7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
13/35
1. Modify the Number object itselfNumber.prototype.changeUnit = function(unit) {this.value = this.value * Number.unitMap[this.getUnit][unit];
}
2. Use a function to return the converted value
Number.prototype.convertUnit = function(unit) {return this.value * Number.unitMap[this.getUnit][unit];
}
Arguments against the arguments against adjusting built-in prototypes
That double-negative is not a typo. As stated before, there are unlimited arguments against modifying
built-in object prototypes. Some are valid, but most are nothing more than opinions about programmingstyle and convention.
(26).doSomething();The above statement, agreeably is confusing and probably not a good practice. But, the method I
discuss above doesn't allow for such "literal processing", as you are required to formally create aNumber object with the new keyword.
var x = new Number(30, Number.units.inches);
This statement can hardly be considered bad style or practice. It uses standard JavaScript objectcreation syntax, spells out clearly that we are using a modified version of the Number object, and
encapsulates the use of units.
At worst, we're trading a questionable JavaScript practice for many rock-solid software construction
practices including abstraction and encapsulation.
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
14/35
5. Assertions are possible
Assertions are a great development-time debugging tool. They allow us to raise a red flag whenever a
condition occurs that should never occur. This is, of course, an entirely different strategy than error-
handling, which is a production-stage, run-time tool that helps to improve a programs robustness by
gracefully "surviving" after an expected error occurs.
Assertion Example: The current object has been initialized before calling this routine
Error-handling Example: User attempted to import a CSV file with 5 rows, instead of the expected 6
rows
Assertions are a handy self-disciplinary tool for the developer, but not all development languages
support them natively. Unfortunately, JavaScript falls into this category. But, the concept behind theassertion is simple, and the code behind the concept is very easy to integrate into any language. Below
is very basic assertion function that can be executed as a statement. It can make use of console logging
or popup dialog alerts. But, the real magic happens when the function "detects" that the script is nolonger in development mode. In this case, it will rewrite itself to a very basic empty function to
improve performance. Cool right!
ASSERT = function(condition, message) {/* the checks below will only be performed in development */
/* during production, if an ASSERT is left in place, it willcause the ASSERT function to rewrite itself to a void, empty functionto improve performance */
/* you can assign appropriate values to local or dev parametersas makes sense by your application */
if(local OR dev) {ASSERT = function(condition, message) {
/* do nothing */}
}else {
if(!condition) {alert(message);// or console.log(message);throw new Error(message);
}
}}
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
15/35
6. Caching function return values
As web applications get more complex, more and more of the processing work is pushed to the client
browser in the form of JavaScript code. We seasoned web developers earned our stripes in the server-
side world, where our own web server executed the code. With this direct tie between a web browser
and our precious server resources, caching was relied upon heavily, not only to improve siteperformance, but to reduce server load, which directly correlates to server operation costs. We had
those two motivations to leverage caching.
With the client-side revolution though, the web developer is seeing a decrease in server load, and an
increase in client (browser) load. Sounds like a dream come true. But, this leads back to the motivationfor performance. We no longer need to rely on our own server resources for performance, but instead
pass the buck onto the user's computer processing power.
The issue isn't solely tied to developer motivation, but also to client-side language support. JavaScript
doesn't offer a built-in caching solution. So, if we have a function which only expects 3 or 4 uniqueargument values over the script's lifetime, and that function happens to take 5 seconds to process, we're
not doing our duty as programmers to put caching to work for the user. After all, we're still going to usethe client's memory for caching, what do we have to lose!
Implementing a function return value cache only takes a few lines of code. Below is pseudocode that issyntactically correct JavaScript. I call it pseudocode because it really doesn't deal with all of the
requirements that a proper cache should have (such as invalidating, lifetime, maximum size, etc). But,
it introduces the concept and provides a foundation.
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
16/35
function Cache() {/* create the cache object as a singleton (only one instance
allowed) */
if(typeof Cache.instance === 'undefined') {Cache.instance = this;
}
var data = [ ]
// we'll abbreviate cacheAwareCall as caCallthis.caCall = function(functionName) {
var cacheCheck = this.load(functionName,this.caCall.arguments);
if (typeof cacheCheck !== 'undefined') {return cacheCheck;
else {var returnValue = window[functionName].apply(this,
this.caCall.arguments)this.save(functionName, this.caCall.arguments,
returnValue);return returnValue;
}}
this.save = function(functionName, argumentObject, returnValue) {// prepend item to cachedata.unshift({ fname: functionName, arguments:
argumentObject, returnValue: returnValue });}
this.load = function(functionName, argumentObject) {for(entry in data) {
if(data[entry]['fname'] === functionName) {// we have a match on the function name// deepCompare is not implemented here, examples are
throughout the webif(deepCompare(argumentObject, data[entry]
['arguments']) {return data[entry]['returnValue'];
}}
}
return undefined;}
return Cache.instance;}
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
17/35
7. JavaScript organization for web development
For those of you who have come across this post, and don't yet know about the object-oriented features
of JavaScript, it will not carry much meaning. I used to be you, believing that JavaScript was only for
validating web forms or making slick rollovers, and further-yet, that object-oriented programming is
really only useful in game development or larger projects.
I don't have the talent to persuade you otherwise, but these two guys do:
Object-Oriented JavaScript: Create scalable, reusable high-quality JavaScript applications and
libraries
If you are in the first camp, not fully understanding the object-oriented nature of JavaScript, Ihave little doubt this book will open your eyes and present the language in a way you never seen
before.
Code Complete: A Practical Handbook of Software Construction, Second EditionIf you are in the second camp, not fully understanding the power of object-oriented
development in general, this book is really a must have. It was a game changer for me many
years ago, and the methodologies are language-independent, so anyone can benefit.
With that being said, and assuming that if you're at this point in the post, you are familiar with OOdevelopment and JavaScript's OO features. You've probably authored a few JavaScript-based web apps,
and are well aware of the challenges it presents when compared with traditional desktop OO
development. Namely:
There isn't a good way to organize classes and packages, and reference them from other classesand packages (unless everything is in one big file).
Splitting classes and packages into multiple folders and files requires multiple HTTP
connections to load all of the code
The asynchronous nature of callbacks is useful, but can add a good deal of complexity to the
even the simplest methods
It's clear from a page load time perspective that condensing all of your classes into one file is the best
choice. But having a few thousand lines of code in one file can make it difficult to locate the exactmethod you are looking for, as well as cause upload-time annoyances as the file grows larger and larger
(if you are developing on a remote server).
To overcome these issues, you can:
1. Do your JavaScript development on your local machine. JavaScript is interpreted inside your
web browser, so it does not require a web server.
Another drawback for some is the same origin policy. If you are developing locally, browsersecurity restrictions disallow you from making cross-domain requests. To get around this
though, many browser have initialization flags that turn this security feature off. For example,
you can start chrome with the disable-web-security option.
2. Use an IDE that recognizes JavaScript objects and organizes them into "classes, methods and
properties" for you. I like Eclipse for this. The Project Explorer pane does a good job of
classifying the objects, i.e.
http://www.amazon.com/gp/product/1847194141/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1847194141&linkCode=as2&tag=site0e5-20http://www.amazon.com/gp/product/1847194141/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1847194141&linkCode=as2&tag=site0e5-20http://www.amazon.com/gp/product/0735619670/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0735619670&linkCode=as2&tag=site0e5-20http://www.amazon.com/gp/product/1847194141/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1847194141&linkCode=as2&tag=site0e5-20http://www.amazon.com/gp/product/1847194141/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1847194141&linkCode=as2&tag=site0e5-20http://www.amazon.com/gp/product/0735619670/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0735619670&linkCode=as2&tag=site0e5-207/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
18/35
Although, I was a little disappointed to find that the project explorer doesn't catch on to this
function definition syntax:
myMethod = function() { }
So, functions defined in this way, within a "class", don't show up in the explorer view.
If you need to develop on a remote server, and prefer to separate your JavaScript classes and packages
into a folder/file hierarchy as is familiar to compiled languages, you're not outta luck. We just have toget creative!
In traditional OO languages, we are accustomed to included individual classes within packages on a"need-to-use" basis, i.e.
import mypackage.myclass
In JavaScript, we're kinda stuck with the tag, which is really only useful for loading in an
entire JavaScript source file. That source file might contain 5 classes or 50 classes, all of which we
must load, regardless of which ones we'll actually use. Because of this limitation, we typically includeall of our classes in one big file. It doesn't have to be this way!
http://www.sitekickr.com/blog/wp-content/uploads/2012/09/eclipse-javascript.png7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
19/35
We can extend JavaScript a bit, including just a few lines of code to emulate the package/class include
methods found in our traditional languages. This of course, requires a few capabilities:
The ability to dynamically load JavaScript files. When I say dynamically, I don't mean "at
runtime", because there's no compiler, everything is at runtime. What I'm talking about is theability to load a JavaScript file from within JavaScript. We know we can do this by dynamically
inserting a tag into our document, and providing it the appropriatesrc attribute.
The ability to determine if a class has already been loaded, so we don't duplicate any efforts.This is possible with the JavaScript typeof operator. For our cases, we need to introduce the
eval function, since we're dealing with a dynamic function name.
A naming convention, so we know which JavaScript file to load, based on which package/class
name was provided. By sticking to the convention of the filename carrying the same name asthe class, and the folder carrying the same name as the package, our little loader will always
know which file to grab.
As Nicholas Zakas points out, we can encapsulate the loading of an external JavaScript file into a
function, and provide a callback to execute after the script has loaded, so our method call might looklike:
loadScript("/mypackage/myclass.js", function(){//initialization code
});
Now, if we alter his script a bit, to use the naming convention we suggested above, the loadScript
function would be more like:
function loadScript(package_class, callback){var className = package_class.split('.').pop();if(eval('typeof ' + className) !== 'undefined'){
callback();}
var script = document.createElement("script")script.type = "text/javascript";
if (script.readyState){ //IEscript.onreadystatechange = function(){
if (script.readyState == "loaded" ||script.readyState == "complete"){
script.onreadystatechange = null;callback();
}
};} else { //Others
script.onload = function(){callback();
};}
script.src = '/' + package_class.replace(/\./g, '/') + '.js';document.getElementsByTagName("head")[0].appendChild(script);
}
http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
20/35
Essentially, we are replacing the dot notation with folder notation, so by callingthis method:
loadScript('Mypackage.Myclass', function(){//initialization code
});
We are actually loading the /Mypackage/Myclass.js file. The Myclass.js file contains a Myclassfunction, which upholds our naming convention. Notice also, in the opening lines of the new loadScript
method, we check to see if the class has already been loaded.
But, what if we want to load multiple classes, and have our callback fire only after all of the external
scripts for those classes have been loaded? One possibility would be to create an array of scriptelements, load them all, then with each onload event, check to see if all scripts have been loaded:
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
21/35
function loadScripts(packages_classes, callback){var scripts = [], scriptCount = packages_classes.length;
for(var i = 0; i < scriptCount; i++ {var className = package_class.split('.').pop();if(eval('typeof ' + className) !== 'undefined'){
scripts[i] = {loaded: true};
}else {
scripts[i] = {loaded: false};}
scripts[i].script = document.createElement("script")scripts[i].script.type = "text/javascript";
if (scripts[i].script.readyState){ //IEscripts[i].script.onreadystatechange = function(){
if (scripts[i].script.readyState == "loaded" ||scripts[i].script.readyState == "complete"){
scripts[i].script.onreadystatechange = null;scripts[i].loaded = true;if(checkAllLoaded()) {callback();
}}
};} else { //Others
scripts[i].script.onload = function(){scripts[i].loaded = true;if(checkAllLoaded()) {callback();
}};
}
scripts[i].script.src = '/' + package_class.replace(/\./g, '/')
+ '.js';document.getElementsByTagName("head")
[0].appendChild(scripts[i].script);}
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
22/35
// private function - check if all scripts have been loadedvar checkAllLoaded = function() {for(var i = 0; i < scriptCount; i++ {
if(!scripts[i].loaded) {return false;
}else {return true;
}}
}}
I have not tested the above code, at all! It's meant to be more theoretical. But, it would appear that
loading multiple external files, and waiting for a callback is possible. So, a method like this, very clean
and consise is actually possible in JavaScript!
loadScripts(['Mypackage.Myclass', 'Mypackage.Myclass2','Myotherpackage.Myotherclass'], function(){
// tie it all together here!
});
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
23/35
8. Avoiding inline JavaScript (and CSS)
Every HTML page consists of three major components:
The skin/template (including meta data)
HTML tags used to wrap the content and provide information about the page
The content
Text marked up with HTML tags
The presentation
CSS rules and JavaScript code
The skin/template should be separated from the content on the server-side, using a framework or layout
method as described in my post on Site Structure. The presentation, however, needs to be separated onthe client-side, using , , and tags. This is one of the oldest and most-commonly-
spoken-of web development practices, and I'd like to go into detail on why this is such a good idea.
Essentially, what separation of content and presentation means is that we are to avoid embedding inline
styles and scripts in our HTML content. For instance, this is a prime example of what not to do:
click
Markup like this is found all over the web, often as a result of inexperienced web coders using
graphical editors, but experienced web developers share the blame too. It's all too easy when 5 o'clock
comes around and your taking every shortcut possible to get out the door, to forgo creating a style class,
and instead just drop those styles right into the HTML tag.
Instead of just frowning on the practice, let's look at a few reasons why this separation is so important:
1. Referencing bare HTML content is more difficult
This reason doesn't present itself right away. It usually comes into play after a website has beenlaunched, and it's content is consumed by services or clients other than a web browser. Because
CSS and JavaScript is only useful to web browsers, anything else which references the content
will either ignore it, or be negatively affected by it. You are, in essence forcing non-browsers toabsorb presentational information when it carries no meaning.
Search engines do a great job of ignoring the presentational items when they index your pages,
but it doesn't mean they like it.
2. Global presentational changes are difficult
This one becomes apparent if you have more than 5 pages on your site, each with inlinepresentational elements. If you have a page title styled as such:
My page
heading
https://www.sitekickr.com/blog/layouts-templates/https://www.sitekickr.com/blog/layouts-templates/7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
24/35
Then, at some point down the road, you decide that green isn't really the look you were going
for with page titles, you need to manually adjust all of your HTML files, to make the inline style
adjustment. This difficulty is compounded with JavaScript, as often times your editor's global
file search/replace feature will be difficult to use against a multiline search.
3. Future-proofing
tags currently validate inside elements (with XHTML you need to use the ugly //!
[CDATA[ trick), but there may be a time when they don't, as the currently does not.
4. Context
During a presidential race, we hear phrases spoken by candidates, but out of context. The phrase
may have carried meaning in the context of the content that surrounded the phrase, but alone, itcarries no meaning or just makes them look bad. The same happens with CSS!
To illustrate, let's say we have a block of content that we want to emphasize heavily by placing
a 50 pixel black border around it, using inline CSS:
This content is soimportant that mobile users need to suffer!
This may present well on a 1024 pixel wide desktop browser, but on a mobile device, the borderitself will take up nearly half the screen. To avoid this, we would typically have separate CSS
files for mobile and desktop. But, there is no such separation when we use inline CSS.
To illustrate in a different way, let's say we have the following inline CSS:
This is a red link
If this content is loaded on a device with a black & white screen, the red link styling is useless
and only served to make the content itself take longer to download.
5. Team environment
If you work in a team, it's likely that you have one team member dedicated to content (HTML),
another to style (CSS), and still another to interactivity (JavaScript).
If you are absent version control and a "check-in" procedure as so many small operations are,
the logical course of action is to restrict access to HTML files to the person who edits theHTML, CSS files to the person who manages the CSS, etc. This serves to prevent one person
from overwriting another's work if they are both accessing the same file at the same time.
That system works well, unless you have CSS and JavaScript embedded in your HTML files. In
this scenario, the person who manages CSS needs to say, "Hey Bob, can you close the file yourworking on for 20 minutes while I edit the inline CSS? When I'm done, don't forget to load the
file from the server again so you don't overwrite my changes. Thanks Bob, you're the best, sorry
for wasting 20 minutes of your day!"
http://javascript.about.com/library/blxhtml.htmhttp://javascript.about.com/library/blxhtml.htmhttp://javascript.about.com/library/blxhtml.htmhttp://javascript.about.com/library/blxhtml.htm7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
25/35
6. Markup to content ratio (bad for search engines)
This one has been preached about by SEO wizards for years, so I apologize for duplicating it
here. However, the list wouldn't be complete without it. Not only does inline style and script
increase page load time, it increases the download time for search engines who are just lookingfor raw content. In effect, a search engine has downloaded additional information that it needs
to discard anyway. This negatively affects how search engines position your site in two ways:
The content vs. markup ratio. It has been suggested the search engines frown when the
amount of markup exceeds the amount of content by an undetermined amount (the ratio,of course, being dependent on the search engine). Without knowing the ideal ratio, it's a
wise practice to keep markup to the absolute minimum required. This includes, of
course, eliminating inline style and script when possible.
Page load. Recent evidence suggests that Google (and perhaps other SEs) factors your
page load time into it's ranking algorithm. Essentially, with all other things being equal,
a site with a faster page load will be ranked higher. As touched upon in the point above,inline style and script increase page load time.
7. Performance
We've touched on how inline style and script can negatively affect performance, but there'sanother side to that. Housing all of your CSS and JavaScript in external files can actually
improve performance drastically. The magic comes from browser caching. A typical web site
frequently updates content, but rarely touches style and interactive areas. With this in mind,most web hosting configurations are set to direct web browsers to cache CSS and JavaScript
files.
By caching these files in the browser, they do not require another HTTP connection to
download them from the server. This post goes into more detail onbrowser caching.
With these seven reasons comes a compelling argument against the use of inline style and script, but by
no means am I saying it is incorrect to do so. It is currently valid, and in very simple sites, may actually
improve performance. In some cases, you can apply an inline style without coming in conflict with any
of the reasons above. But, avoiding inline style and script usually leads to many years of happy andhealthy web coding!
https://www.sitekickr.com/blog/browser-caching-basic/https://www.sitekickr.com/blog/browser-caching-basic/7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
26/35
9. Using barricades for a more robust website
You hear the term robustthrown around loosely."Hey Bob, that new app is gonna be robust, right?"
"Oh yeah Steve, I'm all over that robustness."
But how many people really understand what they're promising? I certainly didn't used to. If youdictionary.com the word robust, you are told that it meansstrongandhealthy. If you try to translate
that meaning to software quality, it become a little ambiguous.
Strong. Does that mean the software can process a lot of data? Or can support a large amount of
concurrent users?
Healthy. Are we talking about how many errors occur within the software? Health is perhaps moreclosely related to robustness, but not exactly.
When talking about software, robustness is how well your code deals with errors, and whether or not
the software can continue to run in the wake of an error. Using the healthiness analogy: Your softwaremay be in perfect shape and run error free 99.9% of the time, but how well does it cope when it catchesa cold? If your software decides who your best friend is on Facebook, no harm done if an error shuts
down the program. But, if your software operates a pacemaker, that .1% probability of an error really
shouldn't shut anything down!
Different web technologies offer different solutions, some not quite as apparent as others. But, beyondsyntax and keywords, there are methodologies that provide robustness. The general approach needs to
be a little different when working with client-side code as opposed to server-side. On the server side we
have more complete error information, as well as logging and notification options that just aren'tpossible (or are more much more difficult to achieve) on the client side.
Server-Side
On the server side, the first step is to decide what the barricade protects. For instance, if you have atwo-column website in which both columns are dynamically generated by your server-side code, you
might want the content column to be entirely unaffected by any errors that occur in the sidebar. A
popular example of this issue occurs within any given WordPress blog. Depending on your PHP errorsettings, an error in your sidebar will "take down" the entire page. With this possibility, it's in your
user's best interest to barricade the sidebar from the rest of the site. For that matter, perhaps the footer
as well.
We can do this with our old friend the try/catch block. By wrapping the entire sidebar code in a
try/catch, we prevent any and all errors from affecting the rest of the site. This still allows our
more "fine-tuned" errors to do their job of properly logging and notifying the user of any errors. But,
we also have the added comfort of being able to log errors from within the "master" catch block.
This doesn't even mention the level of security gained by not exposing error information to potential
hackers.
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
27/35
JavaScript
It seems like every time I come up with a good, solid server-side methodology, it doesn't transfer to
JavaScript! With JavaScript, errors are not displayed front-and-center to the user. They are tucked away
behind a small warning icon in the corner of the browser. But, that doesn't mean they can't do just asmuch harm. As with server-side code, one error in your script and that's it, execution stops.
Of course, we have the same try/catch capability. We could easily wrap an entire chunk of JavaScript ina nice big try/catch. But, how many of us want to wrap our entire script in a try/catch? JavaScript just
doesn't have the useful error reporting that server-side languages have, such as context, line number, etc(some browsers support line number). This would be a debugging nightmare, as the errors would no
longer be picked up by our browser console our true friend in the debugging effort.
JavaScript does, however, treat it's "turn-me-on" tag a little differently than server-side-languages.
"turn-me-on", of course, refers to the tag saying to the browser, "start parsing JavaScript!".
What were you thinking?
The tag is self-contained, error-wise. It is an errorbarricade from the rest of the
tags. Server languages like PHP or ColdFusion don't provide such a barricade. You can
have 30 directives in one PHP file, even divide them up across multiple files. But an error inone ruins the whole batch. Whereas in JavaScript, an error in one tag kills the entire script
within, but doesn't affect the other tags at all.
So, how is this useful?
var x = something; // 'something' is not defineddocument.write('Why won\'t my message display, sadness');
pacemaker.keepOnWorking();document.write('I am unscathed by the errors in my document\'s
other script tag!');
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
28/35
10. Bonus: Ad optimization leveraging JavaScript to
improve RPM
I love highway billboards, and I think they're really effective, at least on me. I do however, wish they
were a bit more dynamic. For one, I've always wondered why they don't include a giant QR code thatpassengers can try to snag with their phone while passing by. If anyone uses this idea, I want 10%. It's
probably been done a thousand times, and I just need to get out more! Okay, digressing from the
subject of the article a bit.
Billboards are great, but they only work while driving in one direction, and if you don't get a chance totake it all in, there's no going back. On the web, the browser scroll bar is analogous to the highway.
Once a user scrolls an advertisement out of view, not only is it no longer visible, but it certainly can't be
clicked. But, no asphalt was laid, and there are no laws against scrolling back up. Yet, how many usersdo you think will actually scroll up to see if they missed any good advertisements? We have more
opportunity to keep our ads within the view of our website visitors, by using JavaScript. Some of the
techniques are so basic that you'll wonder why you haven't been doing them a long time ago.
Keeping ads in view
You don't need a marketing guru to tell you that an advertisement holds no value if you can't see it.There's absolutely no dispute about that fact that you can't click an advertisement if it is not in view. If
you only have one or two ads on your site, it's important to make sure they are always visible, without
being intrusive.
As many ad optimization techniques suggest, keeping ads close to readable text is a good idea. On thisblog, you'll notice that I have one floated in or around the third paragraph. But, what happens when you
scroll down beyond the third paragraph. The advertisement becomes useless.
Now, I certainly don't want to annoy my readers, so moving the ad within the content area would not be
the way to go. It would cause content to shift as line-wrapping changes to support the ad that has beenfloated next to it. I instead opted to move the ad down below the right sidebar when it is scrolled out of
view. This type of movement is accomplished by wrapping the advertisement code in a
element, then moving that with jQuery. In the example below, I have wrapped the AdSense ad
code in a element with an id ofpost-inline-ad.
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
29/35
$(window).scroll(function(){if(siteKickr.isScrolledIntoView($('.entry-content
p').first().next().next())) {if($('#post-inline-ad').hasClass('sidebar')) {
// if ad is in sidebar, move back to paragraph$('#post-inline-ad').removeClass('sidebar');$('.entry-content p').first().next().next().after($
('#post-inline-ad'));}
}else {
if(!$('#post-inline-ad').hasClass('sidebar')) {// if ad is not in sidebar, move to sidebar$('#post-inline-ad').addClass('sidebar');$('.widget-container').last().after($('#post-inline-
ad'));}
}
});
siteKickr = {isScrolledIntoView: function(elem){
var docViewTop = $(window).scrollTop();var docViewBottom = docViewTop + $(window).height();
var elemTop = elem.offset().top;var elemBottom = elemTop + elem.height();
return ((elemBottom =
docViewTop));}
}
This method isn't quite as hardcore as keeping the advertisement in the view regardless of scroll
position, but it gives the user another opportunity to view the ad, where it may previously had not beenin a recognizable position.
Fixed Positioned Element, the CSS way
Of course, there's always the simple, yet effective CSS solution:div#my-ad-wrapper { position: fixed; top: 100px; left: 0; }
Thefixedvalue of the position style specifies that an element remains in the specified position, even ifthe user scrolls. It's similar to the absoluteposition, except that an absolutepositioned item will scroll
with the rest of the static content.
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
30/35
Hey, look over here
Most metrics divide the number of ad impressions by the number of clicks to determine how well
optimized your ad placement is. That works well, but there's another metric to consider is the total
time-on-page for your visitors in relation to ad clicks. If a visitor sits on one page of your site for anhour that's a measure of success in many ways, but if they don't click on a single ad in that hour, then
that visitor may not be as valuable to you as all the other metrics lead you to believe.
If you are a door-to-door vacuum salesperson, asking people for 5 minutes of their time, how
successful would you be if you spent 1 minute giving your pitch, then just stared at them for theremaining 4 minutes.The same thing happens when a visitor loads a page on your site, sees the
advertisements unfold before their eyes, then continues on to read the page content for 5 minutes.
You can keep your visitor engaged in the opportunity to click advertisements by displaying them again
after a certain period of time, unobtrusively. I emphasize the term unobtrusively, as the best way toannoy your visitor would be to surprise them with an advertisement pop-up right over the text they are
reading. But, if you pull a "sidebar surprise", you won't offend your visitor.
Check your analytics tool for pages with high "Avg. Time on Page", to determine which pages would
most benefit from this method:
Then, let's again put JavaScript to work for us, in this case to reveal an advertisement in the sidebarafter the user has been on the page for 60 seconds:
The HTML
X
Thanks for your interest in this article. How about a break to
check out the awesome deals from our friends at:
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
31/35
The CSS
#timed-ad {position: fixed;top: 300px;right: -270px; /* account for width and padding */
width: 250px; |padding: 0 10px;border: 1px solid #000;border-radius: 5px 0 0 5px;background: #eee; }
#timed-ad .close {float: right;margin: 0 -10px 0 0;padding: 5px 8px;color: #fff;background: #555;
cursor: pointer; }
The JavaScript (jQuery)
$('#timed-ad .close').click(function() {$(this).parent().remove();
});setTimeout(function() {$('#timed-ad').animate({ right: -1 }, 2000);
}, 60000); // 60 seconds
Making use of empty real estate
You've no doubt noticed the trend towards wide screen desktop monitors. A website afforded this muchwidth could easily reduce the vertical scrolling necessary to see all of it's content. But, most don't take
advantage, and for good reason. Many users are still on 1024768 monitors. And, even if we used a
responsive layout, to use whatever width is offered by the screen, we still wouldn't want content to span
the full width of a widescreen monitor, it would be difficult to read.
So, what do we do with these large "gutters" on either side of the content. Since we can't use them for
the site content, we might consider using them for something that doesn't affect the purpose of the site
if they can't be seen: advertisements. You could use any number of CSS techniques to force these adsinto the widescreen gutters of the site, but JavaScript certainly provides the most flexibility.
With JavaScript, you can introduce the condition to only display the gutter ads if the site width is
greater than 1400 pixels, for example.
This is, arguably, the least intrusive form of banner advertising on a website. It doesn't intrude on the
content area at all, and users are more than welcome to reduce their browser width if they don't want tobe "bothered" with the advertisements.
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
32/35
The implementation of this method is simpler than the other methods, so I'm going to break my own
rules of separating content, css & script, and package it all up into a small piece of jQuery:
$(window).resize(function() {if($(window).width() > 1400) {
/* widescreen - show gutter ad */if($('#left-gutter-ad').length === 0) {
$('body').append('My ad code goeshere');
}}else {
$('#left-gutter-ad').remove();}
});
$(document).ready(function() {$(window).resize();
});
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
33/35
11. Bonus: Optimize your JavaScript, save the environment
I'm not a tree-hugger, but I'm conscious about the environment. I recycle, drive a 4-cylinder, try to eat
local/organic, and try not to dump paints and varnishes down the kitchen drain. But,I never really
stopped to consider my direct connection to the environment through my coding practices.
When we think about abstraction, we usually don't go further than the operating system or thecomputer processor. We run a high-level language function, it's converted into dozens of low-level
language statements, then hundreds of lines of machine code, which is run by the processor. But, all
that happens under the condition that the processor has power. Let's take a look at the levels of
abstraction that extend beyond your CPU.
Plants
Coal was formed from the remains of vegetation that grew millions of years ago. The plants whichformed coal captured energy from the sun through photosynthesis. This energy is used to create the
elements within plant tissue. The element most important for us being carbon, which gives coal most of
its energy. No environmentally negative factors here.
Coal
Of course, coal is not the only form of energy used to generate electricity, but it's the largest in the US.
Coal power stations have machines that convert the heat energy from the combustion of coal intomechanical energy, which then powers the electric generator. It's the byproducts and wasted heat
energy from this process that causes the negative environmental effects. The process is not 100%
efficient. Those inefficiencies aren't bottled up, they're sent to our air, lakes and rivers.
On average, a ton of coal generates 2,460 kilowatt-hours of electricity. Let's make that simpler:
1 kilowatt-hour of electricy = .81 pounds of coal
The Kilowatt
We Americans aren't fluent in the metric system, but we know the Kilowatt better than any other unit of
measurement when it comes to electricity. Why? Because that's what we see on our electric bill, theKilowatt-hour. But, lets not forget that the kilowatt-hours we use at home don't directly translate to the
kilowatt-hours generated at the power plant. A certain amount of energy is lost in the transmission over
the power lines.
So, how does this translate to our computer's CPU power demands? A kilowatt-hour may be enough topower your light bulb for an entire day, but a CPU is vastly more complex. A light bulb performs one
operation consistently, from the time you turn it on, to the time you turn it off. Calculating it's energyusage is straightforward. But, your computer's processor is more dynamic.
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
34/35
The CPU
CPU's used to maintain a more steady power consumption, but today's CPU is more energy consciouswhen idle. The big question is, "how much energy is saved when it's idle, compared to when it's
working?" Apparently, this is not an easy question. It, of course, depends on who you ask, what the rest
of the system is doing, and which processor. Many forums I visited seemed to suggest that an Intel I7
would drop to 75 watts, from 95 watts when at idle.
I also had difficulty finding out exactly what idle means. Is the processor idle between each sequential
instruction sent its way? Or does it require a length of time before it settles down into it's idle state?
Again, a solid conclusion wasn't reached. So, for this article, I'm going to make the following
assumptions:
The difference between idle and working = 20 watts = .02 kilowatts
Additional Kilowatts used for 1 CPU instruction = the number of hours the instruction takes * .02
I'm emphasizing the word additional, because the CPU uses power whether it's processing an
instruction or not.
The next question: How long does a CPU take to execute one instruction? It varies of course, so let'sagain use the Intel I7. Wikipedia says 82 billion instructions per second! You might be thinking, whyare we possibly concerned with power consumption when we can process 14.7 quadrillion instructions
for just one measly kilowatt-hour!
1 Kilowatt-hour, we remember, is created by the combustion of .81 pounds of coal.
1 pound of coal gets us 18.2 quadrillion instructions. Good job coal, your not so bad after all. But, holdon, we haven't worked our way through the remaining levels of abstraction. How much does 18.2
quadrillion instructions really buy us?
JavaScript
Huh, how did I get to JavaScript? I skipped machine code, assembly language, the OS, the browser
environment. I decided to do this for the dramatic effect of showing how many CPU instructions arerequired for a simple JavaScript statement.
var x = 1 + 1;
I'm now thinking to myself, "how do I begin to determine how many machine code instructions thatlittle statement took?"
I intentionally avoided anything user-interface or input related, to simplify this task.
We first need to find out what JavaScript "sits on". Until Google's V8 engine, JavaScript was
interpreted, and still is in most browsers, by a JavaScript engine. The first JavaScript engine,SpiderMonkey, was written in C++.
C++
What does it take for C++ to run a JavaScript statement such as the one above. I'd have to imagine thatthis particular statement is one-to-one. C++ allows us to declare and initialize a variable in one line of
code, even if that initialization involves arithmetic.
int a = 1 + 1;
7/30/2019 JavaScript Leverage its Strengths to Eliminate its Weaknesses
35/35
Assembly Language
.datax: .word 1y: .word 1a: .word 0
add a,xadd a,yint 21h
Is the above proper assembly langage? No. Will it work? Probably not. I don't know Assembly
Language, I just wanted to illustrate the number of instructions required to perform a simple operation.
In this case, it's likely that each assembly code instruction will produce one line of machine code. So,
the most basic JavaScript statement might translate to at least 7 lines of machine code. I'm talkingabout a statement that involves nothing but the processor and RAM (no display, peripherals, disk drive,
etc). A more complex statement, such as document.write(), may actually consist of hundreds of
machine instructions. So, we can easily see how inefficient JavaScript code is orders of magnitude
more inefficient when you look at it from a machine code standpoint.
But this still doesn't really mean anything. It's too difficult to relate additional lines of machine codedirectly to environmental impact! But, what if we convert that into more recognizable metric, time.
If a set of poorly optimized JavaScript statements takes 100 milliseconds to run, and the optimized
version of that same code takes 50 milliseconds to run, you are keeping that processor busy for 50
milliseconds beyond what is necessary.
50 milliseconds = .05 seconds = .000014 hours
.000014 hours * .02 additional kilowatt hours required by the active CPU = .00000028 kilowatt-hours
So, an additional .00000028 kilowatt-hours are required by your one inefficient algorithm.
Not bad, that only means .00000022 pounds of coal. But, that's just one algorithm, in one page load, byone user.
If your website gets 10,000 page loads today, that number hops up to .0022 pounds of coal wasted.
Yikes, that's getting a little scary!
Over a year, that turns right back into that original .81 pounds of coal, enough to generate 1
kilowatt-hour of electricity, to power the additional CPU cycles required by that same inefficient
algorithm.
Again, that's just ONE algorithm, on one page on the web.
Now, my brain is exhausted from all this math, but multiply this by the number of pages on the web,
and the number of poorly written algorithms on a page, and you've got an awful lot of coal!Who votes that the windows task manager should have another column for "Coal Burned"!
http://www.sitekickr.com/