Tag Archives: Javascript - Page 2

Caching Dom Objects with jQuery

UPDATE

The technique in this post is incorrect and does not work. I failed to realize that jQuery’s selector method (i.e. $() ) always returns a jQuery object. If the element is not in the dom, the jQuery object will be an empty set. But a set nonetheless and not null. Thus, it will never coalesce in the way I intended. I wondered why no-one else was doing this. It seems I have my answer.


I learnt something interesting about JavaScript that I was not aware of this last week. I’ll elaborate by walking you through what I discovered. Basically, I was trying to come up with a pattern that stored a jQuery object, and if for some reason that object had become null at some point, then a failsafe re-query would occur. It looked like this:

  1. Declare a variable
  2. Add it to the pageObjects object, with a cascade to the jQuery selection call
  3. Prime the variable in the document.ready function
  4. All dom manipulations are via the pageObjects object
var someDiv; // step 1

// step 2
var pageObjects = {
  someDivOnPage: someDiv || $('#someDiv'), // different name not necessary, but illustrative
  otherProperty: // ... pageObjects has many properties 
};

//********* document.ready function ********* / 
$(function() {
    // step 3
    someDiv = $('#someDiv');
});

//  ... access object later in script ...
// step 4
pageObjects.someDivOnPage.css('color', #eeeeee);

I discovered, after a while, that this did not work. If that div in one operation was removed from the dom, and re-added in another operation, calling pageObjects.someDivOnPage was undefined. Apparently, the coalesce in that statement was a one-off. That is, the first time pageObjects.someDivOnPage is accessed, the statement coalesces to the jQuery query as planned. But that statement only runs once and the property of that object is stored in a memory location. Once the element underpinning that jQuery object is removed from the dom, that property no longer points to that jQuery object and it doesn’t coalesce to the re-query as it did upon first access.

The proper way to do it is as follows:

var someDiv;

var pageObjects = {
  someDivOnPage: function () {
	return someDiv || $('#someDiv'); // different name not necessary, but illustrative
  },
  otherProperty: // ... pageObjects has many properties 
};

//********* document.ready function ********* / 
$(function() {
    someDiv = $('#someDiv');
});

//  ... access object later in script ...
pageObjects.someDivOnPage().css('color', #eeeeee);

As you can see, I have changed the property in the pageObjects object to be a function. And later on, when I reference that property I call it as a function.

So, the conclusion is that when the interpreter first parses the pageObjects object, the properties are assigned in the way that an expression is executed. To use pseudo code, it would look like this:

// for my first flawed approach.
... {
  someDivOnPage = someDiv || $('#someDiv');
};

// for my corrected approach
... {
  someDivOnPage = function () {
	return someDiv || $('#someDiv'); // different name not necessary, but illustrative
  };
};

That assignment occurs once and the result of that expression is assigned to the property. Makes complete sense really. It’s just something I had not picked up on. Felt like a goose.

So you’re probably wondering about performance? Well, that was the whole idea. The project which I am working on had jQuery performing queries heaps of times for the same dom objects in different operations during the lifecycle of the page (button-clicks, mouse-overs etc.).

If you look at this benchmark which I created at jsperf.com, you will see that this approach is very performant.

The other advantage is that if you are using a good IDE, you get intellisense when you “dot through” to the relevant property on the pageObjects object. This makes maintenance a lot easier and reduces the opportunity for typos when writing out each and every jQuery selector.

Cache Length in for{} Loop or Not

Sometimes things just aren’t the way they are meant to be.

I’ve been reading up on ways to improve the efficiency of my JavaScript. But then, when I do some benchmark testing, the results that come in are a little unexpected.

An example. According to JavaScript luminaries, when you are iterating in a for loop, you can improve performance by using a variable to store the length of whatever collection you are iterating.

for (var i = 0, l = collection.length; i < l; i++) {
    a.num += collection[i];
}

/************* INSTEAD OF *************/

for (var i = 0; i < collection.length; i++) {
    a.num += collection[i];
}

The idea being, that if you don’t have to look up the length variable of the collection in every iteration, then it should run much faster.

Consider this benchmark test that I have created at jsperf.com

The interesting results for Chrome and Firefox were that the difference is negligible (in fact, in some tests the non-cached variable test was quicker). In IE 11, the expected result was reached.

It seems that Chrome and Firefox have built into their AJAX engines some kind of optimisation which is invoked when it sees the for loop structure and does not do the look-up on every iteration.

Of course, there may be something in my test which is not correct and causing the anomaly. I’d be interested in feedback if people think my test could have been written in a better manner. I saw some other tests which called Console.Log() in each iteration of the loop. I thought that was a bad idea as calling that method is probably pretty expensive and would result in bad result data, insofar as the differences would not be discernible owing to the large amount of time taken in each iteration for both types of test.

So I guess the question is, if the browsers compensate for sloppy Javascript, do we need to burn the calories to learn all those optimization tricks? I think so. Just because.

Extant – Testing for null and undefined in One Fell Swoop

I’m currently reading the book Functional JavaScript: Introducing Functional Programming with Underscore.js

Early on in the first chapter, I’ve stumbled upon an awesome line of code which is beautiful in its simplicity and effectiveness. One of the foibles of Javascript is that you have to test for both null values and the undefined value. The following function does that in one sweet line of code:

function existy(x) { 
	return x != null 
};

If x equals undefined, the interpreter will see that it has two values with different types on each side of the != operator. So, it will use type coercion and cast both sides to a boolean value. As null and undefined are both falsey, the function returns false. That is, it is false to say that false does not equal false!
The only problem with it is the name. I’m not really sold on existy. So whenever I use that function, it will be called extant. It can be used as follows:

extant(null);
//=> false
extant(undefined);
//=> false
extant({}.notHere);
//=> false
extant((function(){})());
//=> false
extant(0);
//=> true
extant(false);
//=> true

The thing I love about that function is that it abstracts away the annoyance of checking for undefined and null into one short and sharp function-call. Admittedly, I tended to test for undefined more than null, as null is something typically set by developers, whereas undefined is set by the environment. But still, it’s a lot nicer than:

if(typeof someVariable === 'undefined')

The Javascript Last Value Problem

In this post, I am going to explain the classic “Javascript Last Value” problem better than anyone else on the Internet. Why such a bold claim? Because no-one else goes deep enough in their explanations. I’m going deep and I’m going to use pictures to enable you to visualise what is going on.

A pre-requisite to this post is an understanding of self-invoking functions. If you are unfamiliar with this simple Javascript construct, this article looks about as good as any.

So, what is the Last Value problem? This occurs where functions are declared in a loop. When they are then each executed at a later time, the last value assigned to the “incrementing loop variable” is displayed.

I’ve created a plunk to demonstrate.

Click the Run button and then click the button with the text Click for Young Players Error

You will see the integer 5 displayed on separate lines.

Most programmers new to Javascript look at this code and expect to see 0,1,2,3,4,5 displayed. As we saw, 5,5,5,5,5 was displayed. Why? Time to start explaining stuff…

Lets look at the code which has led to that and examine what is going on.

At line 15 of the script.js file of the plunk, there is a loop which is pushing an anonymous function onto the array called loadWithLogWrites in each iteration of the loop. Don’t worry too much about all the other code around it, as that is just hooking up click-events on the buttons so we can see what’s going on.

Lines 21 to 25 show each of those functions being invoked, the results of each invocation being added to the div called ouptputDiv.

A couple of things to note:

  1. The first thing I want to note is that each of those functions is a separate function. It’s not the same function repeated. Functions are objects and each item in that array is a separate function object (an anonymous function). That is important to realise.
  2. The next important thing to note here is the fact that Javascript does not have block scope. It has function scope. For example, if the following statements are all in the same function, 1 will be successfully logged, even though val is declared and assigned a value inside the block scope of the if statement:
    if(0===0) {
        var val = 1;
    }
    console.log(val); // this is fine and 1 is logged,
    

    If the variable is not inside a function, it is in the Global namespace. What does that mean for our example? Unlike C, C++, C# etc. the variable i is not scoped to the for loop. It is a variable of the Global namespace. To confirm that, go to the plunk, and move var i = 0 to a location out of and above the for loop.

        var i = 0
        for (; i < 5; i += 1) {
          loadWithLogWrites.push(function() {
            return '<div>' + i + '</div>';
          });
        }
    

    You’ll find that nothing has changed. As I said, if i is not in a function, i is scoped to the Global namespace.

With those points in mind, we can see that the functions which have been pushed onto the loadWithLogWrites array all have access to i. Not because it is referenced inside each function; but because it is scoped to the Global namespace and can therefore be referenced from within each function. The Global namespace is in the scope chain of all the functions. I’ve done up a diagram which I want to use to consolidate in your minds the points I have made up until now:

i in Global Namespace

Figure 1 – shows each of the anonymous functions as separate objects, all within the Global namespace

Now to the explanation of why 5s are displayed. It’s really quite simple if we take into account all of the points I made above. Each function has access to i. By the time any of them are invoked (starting on line 21), they have a value of 5. It is the same Global variable i, which they have access to, and that variable was incremented in the for loop to 5.

To elaborate (I like to ram home a point), consider the 2nd function pushed onto the array. At the instance it was pushed onto the array, i had a value of 1. However, i is scoped globally and not to the for loop. By the time that 2nd function is invoked on line 22, i has a value of 5.

So, how do we change the code such that when we click a button, the values 0,1,2,3,4 are displayed? Go back to the plunk and click the button with the text Click for Doing It Properly. You should see some lines of text, starting with item: 0 and can still access global i: 5. Figure 2 pictorially shows what is going on.

IIFEs to the Rescue

Figure 2 – nested functions are created using IIFEs, which close over the “item” parameter

Looking at Figures 1 and 2, I have used different colours for a very good reason (not just to look pretty). Each colour represents a discrete scope. In Figure 1, you can see that each function which is added to the loadWithLogWrites array has its own separate scope. And as explained above, each of those functions has access to the variable i, which is in the Global (light green) scope.

In Figure 2, something very different is happening. The functions which are each being pushed onto the loadWithLogWrites array are being immediately self-invoked. They each also have an inner function which is the one that returns the div (similar to the functions in Figure 1).
And the variable i which is being passed to those self-invoking functions is being created anew as the item parameter inside those functions when they are being self-invoked. This creates a closure which effectively traps that item parameter and its value at the point in time at which it is created. And it is created during the loop.

So, each of the inner functions of the outer functions, which are pushed onto loadWithLogWrites, has access to the

  1. item variable and
  2. i variable

The difference being, the i variable is still in the Global (light green) scope, whereas each discrete item variable is only available in each of the scopes created during the loop. To clarify from a different perspective, in Figure 2, the item variable in the red (outer) and purple (inner) scopes is not available to the light blue (outer) and dark green (inner) scopes (or any of the other scopes for that matter).

Important Final Thoughts

One of the reasons I went through such pains to understand this is because when I was learning JavaScript, there was a statement in a book which I just could not marry up with my understanding of what was going on. That statement was:

Like most modern programming languages, JavaScript uses lexical scoping. This means that functions are executed using the variable scope that was in effect when they were defined, not the variable scope that is in effect when they are invoked.

I thought that functions were executed using the variable scopes that were in effect when they were invoked. But after that in-depth analysis, it became clear to me how the book was correct and that my understanding was wrong.

The Figure 1 scenario is simple. Those variable scopes were all in effect when the functions were defined. Figure 2 took a bit longer to digest. The inner functions are executed using the variable scope which is created when the outer functions are self-invoked. When those are self-invoked, it is at that point that the inner functions are defined. And when they are finally executed in lines 43 – 47 of the plunk, the relevant variable scope is that scope which was in effect when those functions were defined.

Execution Contexts and Scope Chains in Javascript

I was planning to write a post about Execution Contexts and Scope Chains, but my research found a few brilliant articles by a front-end architect named David Shariff who set it out better than I ever could:

  1. What is the Execution Context & Stack in JavaScript?
  2. The this keyword
  3. Identifier Resolution and Closures in the JavaScript Scope Chain

The trigger for my plan was some really bad information. There was an article on codeproject purporting to give answers to interview questions about Javascript. It soon became evident that the article was flawed*. In his article, the following question and answer was set out:

What do you understand by the “this” keyword in JavaScript?

Ans: “this” keyword refers to the current object like other language.

Oh dear. If he really thinks that, he is in for a lifetime of subtle bugs.

Definitely read those articles which I linked to at the top of this post. Shariff provides the foundation for understanding things like identifier resolution and closures. It’s also tremendously important to know what the this identifier is binding to at all times, otherwise you may well find yourself attempting to access things which have the value undefined.

In a response to this stackoverflow question, the poster named Daniel Trebbien included a small quiz which I am reproducing here for posterity (and because it is so good). If you cannot answer these questions, I really recommend reading the resources which I have listed at the top of this post.

(To view the answers, hover over the grey rectangle below each question.)

  1. What is the value of this at line A? Why?
    if (true) {
        // Line A
    }
    
    window
    Line A is evaluated in the initial global execution context. There’s no block scope in javascript. So the if block does not have its own local scope.
  2. What is the value of this at line B? Why?
    var obj = {
        someData: "a string"
    };
    
    function myFun() {
        // Line B
    }
    
    obj.staticFunction = myFun;
    obj.staticFunction();
    
    obj
    When calling a method on an object, this is bound to that object.
  3. What is the value of this at line C? Why?
    var obj = {
        myMethod : function () {
            // Line C
        }
    };
    var myFun = obj.myMethod;
    myFun();
    
    window
    In this example, the JavaScript interpreter enters function code, but because myFun is not called on an object, this is bound to window.
  4. What is the value of this at line D? Why?
    function myFun() {
    	// Line D
    }
    
    var obj = {
    	myMethod : function () {
    	eval("myFun()");
    	}
    };
    
    obj.myMethod();
    
    window
    This one was tricky. When evaluating the eval code, this is obj. However, in the eval code, myFun is not called on an object, so this is set to window for the call.
  5. What is the value of this at line E?
    function myFun() {
        // Line E
    }
    var obj = {
        someData: "a string"
    };
    myFun.call(obj);
    
    obj
    The line myFun.call(obj); is invoking the special built-in function Function.prototype.call(), which accepts thisArg as the first argument. myFun is being called as if it is a method on obj.

As an added bonus, I’ve devised two more quiz questions which are kinda tricky (but simple when you reason it through):

  1. If the following code runs, what is the value of this at line A? Line B? Why?
    //  room is object where nested function is a lambda (or function expression)
    var room = {
        capacity: 10,
        exits: 2,
        count: 0,
        addPerson: function (name) {
            //  Line A
            this.count += 1;
    
            var nestedFunction = function (nameOfPerson) {
                //  Line B
                this.person = nameOfPerson;
            }(name);
        }
    };
    room.addPerson('dave');
    

    Line A – room
    As addPerson is being invoked as a method on the room object, the this variable is bound to the room object.

    Line B – window
    The anonymous function is being executed (self-invoked) as a function and not as a method of any object. That being the case, the this variable is bound to window.

  2. If the following code runs, what is the value of this at line C? Line D? Why?
    var person = 'Bob';
    
    var room = {
    	capacity: 10,
    	exits: 2,
    	count: 0,
    	addPerson: function (name) {
    		//  Line C
    		this.count += 1;
    
    		var nestedFunction = function (nameOfPerson) {
    			//  Line D
    			this.person = nameOfPerson;
    		};
    
    		return nestedFunction;
    	}
    };
    
    var otherRoom = {
    
      person: 'dave'
    
    };
    
    otherRoom.changePersonName = room.addPerson('');
    otherRoom.changePersonName('Joe');
    

    Line C – room
    Again, as addPerson is being invoked as a method on the room object, the this variable is bound to the room object. Things get a bit more interesting when we look at line D.

    Line D – otherRoom
    In this case, the anonymous function is being returned by the addPerson method, and it is being assigned to the changePersonName member of otherRoom. When changePersonName is invoked, it is done so as a method of otherRoom.

There’s another pretty cool resource I found on execution context which can be found in this this sample chapter of the book Even Faster Websites. The first figure is really good but it does have one one technical mistake in it, which I have corrected. Click here to see the corrected image.

Execution Context and Scope

Num2 is not a part of the Global scope and I removed it from the Global object in the diagram

* many people post articles on codeproject to pad their resume. Unfortunately, some people don’t have any idea about what they’re writing about. And this is made worse by other people up-voting their article with 5 stars.