Skip to Content

Before we start, let’s look into the code below. What will be displayed in alert popup?

/wp-content/uploads/2015/12/clipboard1_845455.png

When function f is called, x = 3, y = 2. The main question here is inside function f, what is the value of x, 2 ( the original value when an anonymous function is assigned to variable f via function expression ) or 3 ( the actual value in the runtime ) ?

/wp-content/uploads/2015/12/clipboard2_845483.png

The answer is 3, so finally we get 3 displayed in popup.

/wp-content/uploads/2015/12/clipboard3_845484.png

Now check this example:

/wp-content/uploads/2015/12/clipboard4_845485.png

and we will get 2 this time, since the free variable x is bound to value of the lexical environment at declaration time, 2.

/wp-content/uploads/2015/12/clipboard5_845495.png

Example1 – AJAX callback

before we use Closure

In order to get which button is being clicked, we have to make use of oEvent passed in:

<html>
<body onload = "load();">
<div>
 <button id="button1" width = "100px">button1</button>
 <button id="button2" width = "100px">button2</button>
</div>
</body>
<script>
function load() {
 registerEvent("button1");
 registerEvent("button2");
}
function registerEvent(buttonID) {
 var oButton = document.getElementById(buttonID);
 if( !oButton)
  return;
 oButton.onclick = function(oEvent) {
  debugger;
  alert("button clicked, id: " + oEvent.srcElement.id);
 };
}
</script>
</html>

after we use Closure

function registerEvent(buttonID) {
 var oButton = document.getElementById(buttonID);
 if( !oButton)
  return;
 oButton.onclick = (function() {
  return function(){
   alert("button clicked, id: " + oButton.id);
  }
 })();
}

The parameter oEvent is no longer needed.

/wp-content/uploads/2015/12/clipboard6_845496.png

Example 2 – Resource Lazy load design

Suppose when we try to log on WebQQ, the desktop background color should become dark to highlight the logon dialog.

/wp-content/uploads/2015/12/0_845497.jpeg

Solution version 1

Create a new div element used as a mask layer.

var createMask = function(){
  return document,body.appendChild(  document.createElement("div")  );
};
$('button').click(function(){
  var mask  = createMask();
  mask.show();
});

 

Drawback: It makes sense for the mask div element to be a singleton, or else every time we click log on button, there will be a new div generated.

Solution version 2

I use the following code to achieve singleton.

var mask = document.body.appendChild(document.createElement(''div" ) );
$( ''button').click(function(){
  mask.show();
});

 

Drawback: If log on button is never clicked, the mask div element is then not necessary. In this solution, the mask div is always created although not necessary.

Solution version 3

I use a global variable to check whether the mask div has already been created or not.

var mask;
var createMask = function(){
 if(mask)
   return mask;
 else {
   mask = document,body.appendChild(  document.createElement(div)  );
   return mask;
 }
}
Drawback: here a global variable outside createMask function is used and it is changed inside createMask. This is not safe since there is possibility that other JS file could also change it.

Solution version 4

 

var createMask = function() {
  var mask;
  return function() {
      return mask || ( mask = document.body.appendChild(document.createElement('div')));
  }
}();

 

Now the mask variable is wrapped inside Closure and not visible to outside consumers. The creation of mask div is delayed until it is really necessary.

Final solution

We can also write a generic function to enable any other function to behave as singleton style:

var singleton = function(fn){
    var result;
    return function() {
        return result || ( result = fn.apply(this,arguments));
    }
}

 

The singleton function accepts a function as input, and return a new function which behaves like singleton.

Our final solution could be:

var createMask = singleton(function(){
  return document.body.appendChild(document.createElement('div'));
});

Simple test it. When createMask is created for the first time, result is initial, so the code after || is called to fill the result.

When called the second time, the result is returned directly.

/wp-content/uploads/2015/12/clipboard9_845504.png

/wp-content/uploads/2015/12/clipboard10_845505.png

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply