• Semantics of undefined and null in javascript

    Recently, I was discussing with a friend about the difference between undefined and null in javascript. I am surprised that I gave an explanation that he can understand, more surprisingly, I can understand too. Sometimes, people give an explanation, which they don't understand themselves, and also confuse others. Before going further, here is the explanation from JavaScript: The Definitive Guide

    You might consider undefined to represent a system-level, unexpected, or error-like absence of value and null to represent program-level, normal, or expected absence of value. If you need to assign one of these values to a variable or property or pass one of these values to a function, null is almost always the right choice.

    The explanation is confusing to me. What does this means in my daily coding, in what scenario I must use one but not the other or a scenario I can use either of them? So if null is almost the right choice, but why we have "undefined", is there any technical reason or semantic reason? Let's see why we have "undefined" value in javascript from technical perspective. When we write the following code, I can say, I declare two variables and they are not assigned with any value, and the default value of each is undefined.

    var x;
    var loooooooooooooooooooooooooong;
    

    After reading the article Understand delete, I understand that, javascript variable mechanism. When you declared variable like above, you add a key/value pair entry to a mysterious object, VariableObject, which is dictionary. Here is pseudo code, that the engine will convert to

    VariableObject["x"] = undefined;
    VariableObject["loooooooooooooooooooooooooong"] = undefined;
    //semantically, it means the following
    //VariableObject.add("x", undefined);
    //VariableObject.add("loooooooooooooooooooooooooong", undefined);
    

    If the above example, two key/value pairs are added to the VariableObject dictionary. So both the key and value consume memory, so if you have a longer variable name, regardless its value, it use more memory than short variable. This is different from c++. In c++, a variable name is nick name of memory address. So practically, we should use shorter variable name, or use minifier to rename your variable. The VariableObject is special in that it is created by runtime. If the code is run in Global scope, the VariableObject is accessible as window. If it is run function scope, it is not accessible at all, which is known as Activation Object. Supposed it is run in global scope, it is same as the following.

    window["x"] = undefined;
    window["loooooooooooooooooooooooooong"] = undefined;
    

    In the above case, variable x is said declared because its key is in the dictiobary, but its value is undefined. If the key is not even in the dictionary, then it is undeclared. Technically, there is difference between "undeclared" and "declared but undefined". But the following undefined check does not tell the difference.

    //suggested by jQuery Code Style Guildeline
    //http://docs.jquery.com/JQuery_Core_Style_Guidelines
    //undefined check
    //Global Variables: 
    typeof variable === "undefined"
    //Local Variables: 
    variable === undefined
    //Properties: 
    object.prop === undefined
    

    If you really need to know the difference, you need to use catch, because accessing undeclared variable directly will throw an exception.

    function test(variableName) {
      try {
         var temp = eval(variableName);
        if (temp === undefined) {
           return "\"" + variableName + "\" is declared, its value is undefined"; 
        } else {
           return "\"" + variableName + "\" is declared, its value is not undefined"; 
        }
      } catch (e) {
          return "\"" + variableName + "\" is undeclared";
      }
    }
    
    
  • matrix.js introduction

    Essentially, matrix.js is like other script loader, but it does other things such extensible resource type, dependencies registration and reload, resource locations, resource release and others. In the following, I will explain what the library can do. All these example presented here can be found at GitHub

  • tweaking HTTP header to imporve performance

    Lately, I am doing some client side optimization. One of the techniques is cache. When browser firstly request a resource and get the response, the cache subsystem of the browser need to determine whether to cache resource. It is based on the response header Cache-Control, and Expires. When neither of them exists in the response header, browsers use their own strategy to cache, these strategies vary from browser to browser, so they are not predictable, we should explicitly set these headers. To explicitly disable cache in browser, we can use the following

    Pragma: no-cache 
    or
    Cache-Control: no-cache 
    or
    Cache-Control: no-store
    

    The Pragma: no-cache header is included in HTTP 1.1 for backward compatibility with HTTP 1.0+. It is technically valid and defined only for HTTP requests; however, it is widely used as an extension header for both HTTP 1.0 and 1.1 requests and responses. HTTP 1.1 applications should use Cache-Control: no-cache, except when dealing with HTTP 1.0 applications, which understand only Pragma: no-cache. According RFC 2616, Cache-Control: no-cahce is semantically different from Cache-Control: no-store. non-cache still allows browser cache a response, and the cache needs to re-validate the response with the origin server before serving it. no-store request browser not to cache response at all. However most browser treat "no-cache" as "no-store".
    To implement the semantics of "no-cache", we should use Cache-Control: max-age=0 or Cache-Control: s-maxage=0 or Cache-Control: must-revalidate.

    To explicitly to cache resource, we should use the following.

    Cache-Control: max-age=3600
    Cache-Control: s-maxage=3600
    //or
    Expires: Fri, 05 Jul 2002, 05:00:00 GMT
    

    The Cache-Control: max-age header indicates the number of seconds since it came from the server for which a document can be considered fresh. There is also an s-maxage header (note the absence of a hyphen in "maxage") that acts like max-age but applies only to shared (public) caches. The deprecated Expires header specifies an actual expiration date instead of a time in seconds. The HTTP designers later decided that, because many servers have unsynchronized or incorrect clocks, it would be better to represent expiration in elapsed seconds, rather than absolute time. An analogous freshness lifetime can be calculated by computing the number of seconds difference between the expires value and the date value.

    If browser hit the same url again, browser will firstly ask the cache sub-system to get a cache copy. If the cache is still fresh based on "Cache-Control" or "Expires" header, the cache is returned, and no request is sent to server. If the cache expired, determined whether a validator was send from the previous response, different request will be sent. If a validator of previous response is "Last-Modified", the following will apply.

    //validator of previous response
    Last-Modified: Sun, 03 Apr 2011 14:34:43 GMT
    
    
  • A enhanced curry method

    JavaScript is a functional language, it supports function composition, we can do curry with JavaScript. Douglas Crockford has defined "curry" method in his book JavaScript: The Good Parts to facilitate the steps to define curried function.

    Function.prototype.method = function ( name, func ) {
     if ( !this.prototype[name] ) {
      this.prototype[name] = func;
     }
    };
    
    
  • the when method

    In jQuery 1.5, there is a "when" method.

    function when(objects) {}