JavaScript: You think you know it well?

Just because you are a C# or Java developer that you think you know JavaScript well.  Well I don’t.  But no worries, below are some quick pointers to remember:

  • null and undefined are types, just like Numbers, Strings, Booleans, and Objects.  null indicates a deliberate non-value while undefined indicates an uninitialized value.
  • Primitive/literal values (null, undefined, “string”, 10, true, false) are converted to objects (wrapper objects) when properties are accessed.
  • Functions and Arrays are special types of objects.
  • Built in Error types are there as well.
  • Object(), Array(), String(), Number(), Boolean(), Function(), Date(), RegExp(), and Error() are native constructor functions.
  • parseInt() and parseFloat() parse the number in string until it reaches an invalid character.
  • Unary + operator converts values to numbers (+ “42” = 42 ) and returns NaN (Not a Number) if non-numeric.
  • isNaN() tests for NaN.
  • isFinite() tests for Infinity (1/0), -Infinity (-1/0), and NaN.
  • false, 0, empty string (“” ), NaN, null, and undefined convert to false, and all others convert to true.
  • Blocks do not have scope, only functions have scope.
  • “3” + 4 + 5 = 345, while 3 + 4 + “5” = 75.
  • Triple-equals operator avoids type coercion.  1 === true is false, but true === true is true.
  • JavaScript objects are simple collections of name-value pairs where the name is a JavaScript string and the value is any JavaScript value.
  • array.length isn’t necessarily the number of items in the array.  It is one more than the highest index.
  • No return statement or empty return with no value in a function returns undefined.
  • arguments variable contains all the values passed to the function.
  • IIFEs (Immediately Invoked Function Expressions) is basically what it says.  It’s a function in an expression and invoked immediately ( (function () { … })();  )
  • To call functions recursively, you can use a named IIFE ( (function myFunc() { myFunc(); })();  ).  The name is only available to the function’s own scope.
  • this inside a function refers to the current object if the function is called against an object or using dot notation or bracket notation; otherwise it will refer to the global object.
  • Global object or the head object in JavaScript in a web browser environment is the window object.  Variables you declare globally in your JavaScript code will become properties of the window object.
  • JavaScript does not have classes; it only has object prototypes. It uses functions as classes.  You declare the properties inside the function and declare the methods by assigning them to the function object’s prototype.
  • prototype is an object shared by all instances of the object.  It forms part of a lookup chain, which has a special name called prototype chain.  Anything assigned to the object’s prototype becomes available to all instances of the object.
  • Inner or nested functions can access variables in their parent function’s scope.
  • Closure happens when an outer function returns the inner function and the inner function needs access to the outer function’s local variables.  The outer function’s scope object is actually retained even after the outer function has returned.  Only when there are no more references to the inner function will the outer function’s scope object be garbage collected.
  • Scope objects form a chain called the scope chain.  Scope object is created every time the function starts executing.

JavaScript: Attaching/Detaching Event, OnLoad vs. DOMContentLoaded, Manipulating DOM and CSS

Event Handling, Attaching and Detaching Events

3 phases of event dispatch:

  • Capturing – going down the DOM tree until it reaches the target element
  • Target
  • Bubbling – going back up the DOM tree from the target element

 

// standard way of accessing the Event object
var eventHandlerDOM = function(evt) {
alert(evt.type); //displays click
}

// starting IE 9 you can use the standard way
var eventHandlerIE8Older = function() {
var evt = window.event;
alert(evt.type);
}

// cross-browser way
var eventHandlerCB = function(evt) {
if (!evt) evt = window.event;
alert(evt.type);
}

window.onload = function() {
var btn = document.getElementById("btn");

// 2 ways of attaching an event
btn.onclick = eventHandlerCB;
// or ...
if (btn.addEventListener) {
btn.addEventListener("click", eventHandlerCB, false);
}
else {
// starting IE 9, you can use the standard way using
// addEventListener
btn.attachEvent("onclick", eventHandlerCB);
}

alert("events attached");
alert("now detaching events...");
detachEvents();
alert("events detached");
}

// detaching events
var detachEvents = function() {
if (btn.removeEventListener) {
btn.removeEventListener("click", eventHandlerCB, false);
}
else {
// starting IE 9, you can use the standard way using
// removeEventListener
btn.detachEvent("onclick", eventHandlerCB);
}
}

 

window.onload Event vs. document.DOMContentLoaded event

The problem with running script on window.onload event is that if you have a rather large image to download, your script will run only after the image is downloaded.  window.onload event is triggered after everything, including external stylesheets, javascript files and images, has been downloaded.  An alternative, and usually a best practice, is to run your script on document.DOMContentLoaded event.

var readyFunc = function() {
var stat = document.getElementById("statDOMReady");
stat.innerHTML = "DOM is ready!!!";
}

document.addEventListener("DOMContentLoaded", readyFunc, false);

 

Note that document.DOMContentLoaded event is an HTML5 specification.  Also if your script needs to work with CSS, you need to put all your external stylesheets in the header and all your external scripts in the footer so all the styles will be loaded before your scripts are run.

 

Manipulating DOM

A sample of what you can do for manipulating DOM:

  • document.createElement() – create an Element node
  • document.createTextNode() –  create a Text node
  • element.cloneNode() – create a copy of a node and its attributes with option to include the descendants as well
  • element.appendChild() – add a new child node as the last child node
  • element.insertBefore() – insert a new child node before a specified child node
  • element.removeChild() – remove a child node
  • element.replaceChild() – replace a child node
  • document.createDocumentFragment() – create an imaginary Node object; useful for adding content to your document, or extracting parts of your document and modifying it and inserting it back

 

Manipulating CSS

2 ways to import external stylesheets:

<!-- using <style> tag and @import -->
<style type="text/css">
@import "myStylesheet.css";
</style>

<!-- using <link> tag and rel="stylesheet" -->
<link type="text/css" href="myStylesheet.css" rel="stylesheet" />


 

Persistent, preferred, and alternate stylesheets:

<!-- persistent stylesheet -->
<link type="text/css" href="main.css" rel="stylesheet" />

<!-- preferred stylesheet -->
<link type="text/css" href="dflt.css" rel="stylesheet" title="Default" />

<!-- alternate stylesheet -->
<link type="text/css" href="alt1.css" rel="alternate stylesheet"
title="Alternate 1" />

 

element.style, window.getComputedSyle(), element.currentStyle, elements positioning properties:

var p1 = document.getElementById("p1");
p1.style.fontSize = "20px";

// standard way of getting the computed style
var computedStyle = window.getComputedStyle(p1, null);
alert(computedStyle.fontSize); // displays 20px

// IE way of getting the computed syle
// starting from IE9, you can use the standard way
var computedStyle2 = p1.currentStyle;
alert(computedStyle2.fontSize); // displays 20px

// cross-browser code for getting the computed style
if ( !("getComputedStyle" in window) ) {
alert("getComputedStyle does not exist")
window.getComputedStyle = function(element) {
return element.currentStyle;
}
}

// positioning properties of an element you can use
alert(p1.offsetTop); // displays 130
alert(p1.offsetLeft); // displays 8
alert(p1.offsetHeight); // displays 23
alert(p1.offsetWidth); // displays 911
// below will display 0, because it's parent is the body tag
alert(p1.offsetParent.offsetTop);
var body = document.getElementsByTagName("body")[0];
alert(body.offsetTop); // displays 0

JavaScript: RegExp, Error, DOM, and Event

This post is a follow-up to my previous posts, Object Oriented Programming In Javascript and JavaScript Array and How It’s Different from Object.  In this post I will touch on regular expressions, error handling, basic DOM scripting, image preloading, and timing events.

 

Regular Expressions

// creating patterns
var pattern1 = new RegExp("Rodan"); // using constructor
var pattern2 = /Rodan/; // using literal enclosed in "/"

// testing strings against the patterns
alert(pattern1.test("Rodan Sotto")); // displays true
alert(pattern2.test("John Doe")); // displays false

// using String methods search, match, and replace with regular expressions
var string1 = "Rodan Sotto";
var string2 = "John Doe";

// below will display 6, the starting position of the substring found
alert(string1.search(/Sotto/));
// below will display -1, which means no substring found
alert(string2.search(/Sotto/));

alert(string1.match(/Sotto/)); // displays an array ["Sotto"]
alert(string2.match(/Sotto/)); // displays null

// below will display "Rodan Nolastname"
alert(string1.replace(/Sotto/, "Nolastname"));
// below will display "John Doe"
alert(string2.replace(/Sotto/, "Nolastname"));

See JavaScript RegExp Object for more information.

 

Error Handling

var testErrorHandling = function () {
try {
alert("Throwing an error inside the try block...");
throw(new Error("You've got an error!!!"));
}
catch (error) {
alert(error.message);
}
finally {
alert("Error or not, finally will get executed");
}
};

 

Basic DOM Scripting

W3Schools.com has a very good beginner resource on HTML DOM.

  • DOM stands for Document Object Model.  Everything in DOM is a node.  A Node can be any of the following:
    • Document Node
    • Element Node
    • Attribute Node
    • Text Node
    • Comment Node
  • Document Object, which represents your web page, is the first object you will need to access the DOM.  It is the root node of the HTML document and the owner of all other nodes.  See Document Object Properties and Methods.
  • Element Object, which represents an HTML element, is the second object you will need to access the DOM.  Most commonly a call to document.getElementById() method will return an element object.  An element object is also an element node.  It can have child nodes such as element nodes, attribute nodes, text nodes, or comment nodes.  See Element Object Properties and Methods.
  • An Element Object can be one of the following:
    • Anchor Object
    • Image Object
    • Button Object
    • etc., each of which can have it’s own set of properties and method.
  • And lastly, the Attr Object which represents an HTML attribute and always belongs to an HTML element.  See Attr Object Properties and Methods.
  • Events.  See HTML DOM Events.  It lists the different events such as:
    • Mouse Events
    • Keyboard Events
    • Frame/Object Events
    • Form Events
    • It also lists the properties and methods of event objects that event handlers have access to such as:
      • Event Object
      • EventTarget Object
      • EventListener Object
      • DocumentEvent Object
      • MouseEvent Object
      • KeyboardEvent Object

 

Default Action Cancellation

var event_handler = function(evt) {
if (!evt) evt = window.event; // for IE

// ...

// cancel default action
if (evt.preventDefault) {
evt.preventDefault(); // for most browsers
}
else {
evt.returnValue = false; // for IE
}
}

window.onload = function() {
var link = document.getElementById("link");
link.onclick = event_handler;
}

 

Image Preloading

var image = new Image();
image.src = "image.jpg";
// or
image.src = link.href;

 

Timing Events

JavaScript also provides for executing code at specific time-intervals using setInterval() and setTimeout() methods.  See JavaScript Timing Events.  

So what is Closure?

I’m not talking about closure in a relationship :).  I am talking about closure in programming.  I first encountered closure in JavaScript the hard way.  I was debugging for days the following code as to why it was not behaving the way I expect it to be.

var setRowsOnclickEvent = function () {
    var table = $("tableList");
    
    for (var i = 1; i < table.rows.length; i++) {
        var row = table.rows[i];
        
        row.onclick = function () {
            var table = $("tableList");
            
            for (var j = 1; j < table.rows.length; j++) {
                var row = table.rows[j];
                
                if (j == i) {
                    row.className = "selectRow";
                }
                else {
                    row.className = "unselectRow";
                }
            }
        }
    }
}

 

 

The JavaScript function above is setting the onclick event of all the rows in the table.  It iterates through each row in the table and assigns an inline function, an event handler, to the row’s onclick event.  Note that the event handler, or the inner function, uses the loop variable i of the outer function, containing the row number, so that whenever the row is clicked it get’s highlighted.

My mistake was to think that the value of i is passed on to the event handler like a function parameter and placed on the stack.  Don’t make that mistake. The value of i actually closes on you, I mean on the event handler, or the inner function.  So variable i is a closure variable, while the inner function is a closure function.

Again don’t make the mistake that assigning the event handler to the onclick event actually calls the event handler.  It’s an event handler so it can be called even after the outer function has been out of scope.

So you ask, what happens to the value of i then? Well for closure situations like this, the compiler creates a special context object containing the closure variables so that closure functions, when they get executed, will have access to these variables even if the function that the closure variables are declared in are already out of scope.

In the above JavaScript code, what’s happening is whenever any row is clicked, the last row always gets highlighted, so which is to say, the variable i always has the value of the last row number.  The reason is because, again, even if the closure function, or the event handler in our example, is inside a loop that iterates through each row and incrementing the closure variable i, when the loop exits, the closure variable i will contain the last value in the loop which is the last row number and that is the value that the event handler will get when it gets executed at a later time.  So the value of the closure variable i will be the value at runtime and not at capture time, or in our example, not at the time when the event handler is declared and assigned.

Below is my solution to the JavaScript code above.  The solution is to wrap the event handler in another function where I pass in i as a function parameter, thereby forcing the compiler to capture the value of i as it increments itself inside the loop.

var setRowsOnclickEvent = function () {
    var table = $("tableList");
    
    for (var i = 1; i < table.rows.length; i++) {
        var row = table.rows[i];
        
        row.onclick = (function (i) {
            return function () {
                var table = $("tableList");
                
                for (var j = 1; j < table.rows.length; j++) {
                    var row = table.rows[j];
                    
                    if (j == i) {
                        row.className = "selectRow";
                    }
                    else {
                        row.className = "unselectRow";
                    }
                }
            }           
        })(i);
    }
}

 

 

EDIT:  The code above works by making the function (outer function) that wraps the event handler (inner function) as an IIFE (Immediately Invoked Function Expressions).  This creates a scope object for the outer function (remember Javascript scoping stops at the function level while C# continues at the block level) containing the current value of i in the loop which is retained even after the outer function has returned.  Then each row’s onclick event will end up having an inner function with access to a separate outer function’s scope object, each containing a different value of i.

It’s not only the JavaScript language that has closure.  Other languages have it as well, like C#.  I encountered closure in C# the same way I did in JavaScript.  I was declaring/passing in a lambda expression to a function call inside a foreach loop, that references the foreach variable.  And since C# has a slightly different handling of closure than JavaScript, the solution is different.  In C#, one just need to assign the foreach or loop variable to a temporary variable and reference the temporary variable instead.

public void SomeFunction()
{
    // ...
    foreach (Filter filter in filters)
    {
        // have to assign filter value to temp variable in the loop
        //  because the lambda expression we're using here is in a closure
        string filterVal = filter.Value;
        switch (filter.Field)
        {
            case "Location Name":
                locs = locs.Where(l => l.LocationName.Contains(filterVal));
                break;
            // ...
        }
    }
    // ...
}

 

 

It’s not easy to wrap your mind around closure, at least for me.  Closures in C# vs JavaScript – Same But Different really explains it to me clearly, from a really really technical point of view, as in how the compiler handles closure both in C# and JavaScript.  Don’t worry it’s not a long read but one needs to really read through the code. I’ve got other links for further reading if need be:

I can’t guarantee you to become a closure relationship expert, but after going through the readings and links above,  I can guarantee you to become a closure programming expert ;).

JavaScript Array and How It’s Different from Object

It’s important to know arrays and objects in JavaScript because they are often used to store client-side data.  Below are quick points on arrays and objects:

// arrays and objects can be confusing at first
// just remember that arrays in Javascript are ordered lists
// and are normally looped through using numerical index starting with 0
// objects, on the other hand, have property names associated with values
// confusion always happen when objects are used like associative arrays,
// arrays that use names as index to access their associated values


// declaring an array

// as an empty array
var myArray1 = [];
alert(myArray1.length); // displays 0, since it"s empty

// with initialized values
var myArray2 = ["apple", "orange", "banana", "strawberry"];
alert(myArray2[1]); // displays orange, the second element in the array

// using Array constructor
var myArray3 = new Array("red", "green", "blue");
alert(myArray3.join(", ")); // displays red, green, blue


// object on the other hand has a different declaration syntax
// while array is declared using square brackets [],
// object is declared using curly braces {}
// BUT both use [] to access their elements/properties
var myObject1 = {};
var myObject2 = {
"fruit1": "apple",
"fruit2": "orange",
"fruit3": "banana",
"fruit4": "strawberry"
}
alert(myObject2["fruit2"]); // displays orange


// one method that is quite used most often for arrays is the push() method
// it"s a convenient way to add to your array
alert(myArray2.length); // displays 4
myArray2.push("grape");
myArray2.push("cherry");
alert(myArray2.length); // displays 6, after adding 2 more in the array

 

Hopefully that helps clarify the confusion.

JavaScript Kit has a comprehensive reference with explanations and examples including reference to Array object that you might want to look further into; definitely a good resource to add to your toolbox.  I already had it added to my Favorite Links.

Also, Fun with JavaScript Native Array Functions talks about a slew of array functions in detail.