views:

146

answers:

2

Question: There seem to be many benefits to Closures, but what are the negatives (memory leakage? obfuscation problems? bandwidth increasage?)? Additionally, is my understanding of Closures correct? Finally, once closures are created, can they be destroyed?

I've been reading a little bit about Javascript Closures. I hope someone a little more knowledgeable will guide my assertions, correcting me where wrong.

Benefits of Closures:

  1. Encapsulate the variables to a local scope, by using an internal function. The anonymity of the function is insignificant.

What I've found helpful is to do some basic testing, regarding local/global scope:

<script type="text/javascript">

   var global_text  = "";
   var global_count = 0;
   var global_num1  = 10;
   var global_num2  = 20;
   var global_num3  = 30;

   function outerFunc() {

      var local_count = local_count || 0;

      alert("global_num1: " + global_num1);    // global_num1: undefined
      var global_num1  = global_num1 || 0;
      alert("global_num1: " + global_num1);    // global_num1: 0

      alert("global_num2: " + global_num2);    // global_num2: 20
      global_num2  = global_num2 || 0;         // (notice) no definition with 'var'
      alert("global_num2: " + global_num2);    // global_num2: 20
      global_num2  = 0;

      alert("local_count: " + local_count);    // local_count: 0

      function output() {
         global_num3++;

         alert("local_count:  " + local_count  + "\n" +
               "global_count: " + global_count + "\n" +
               "global_text:  " + global_text
              );

         local_count++; 
      }

      local_count++;
      global_count++;

      return output;  
   }  

   var myFunc = outerFunc();

   myFunc();
      /* Outputs:
       **********************
       * local_count:  1
       * global_count: 1
       * global_text: 
       **********************/

   global_text = "global";
   myFunc();
      /* Outputs:
       **********************
       * local_count:  2
       * global_count: 1
       * global_text:  global
       **********************/

   var local_count = 100;
   myFunc();
      /* Outputs:
       **********************
       * local_count:  3
       * global_count: 1
       * global_text:  global
       **********************/


   alert("global_num1: " + global_num1);      // global_num1: 10
   alert("global_num2: " + global_num2);      // global_num2: 0
   alert("global_num3: " + global_num3);      // global_num3: 33

</script>

Interesting things I took out of it:

  1. The alerts in outerFunc are only called once, which is when the outerFunc call is assigned to myFunc (myFunc = outerFunc()). This assignment seems to keep the outerFunc open, in what I would like to call a persistent state.

  2. Everytime myFunc is called, the return is executed. In this case, the return is the internal function.

  3. Something really interesting is the localization that occurs when defining local variables. Notice the difference in the first alert between global_num1 and global_num2, even before the variable is trying to be created, global_num1 is considered undefined because the 'var' was used to signify a local variable to that function. -- This has been talked about before, in the order of operation for the Javascript engine, it's just nice to see this put to work.

  4. Globals can still be used, but local variables will override them. Notice before the third myFunc call, a global variable called local_count is created, but it as no effect on the internal function, which has a variable that goes by the same name. Conversely, each function call has the ability to modify global variables, as noticed by global_var3.

Post Thoughts: Even though the code is straightforward, it is cluttered by alerts for you guys, so you can plug and play.

I know there are other examples of closures, many of which use anonymous functions in combination with looping structures, but I think this is good for a 101-starter course to see the effects.

The one thing I'm concerned with is the negative impact closures will have on memory. Because it keeps the function environment open, it is also keeping those variables stored in memory, which may/may not have performance implications, especially regarding DOM traversals and garbage collection. I'm also not sure what kind of role this will play in terms of memory leakage and I'm not sure if the closure can be removed from memory by a simple "delete myFunc;."

Hope this helps someone,

vol7ron

+6  A: 

You may get a raft of good answers. One certain negative is the Internet Explorer circular reference memory leak. Basically, "circular" references to DOM objects are not recognized as collectible by JScript. It's easy to create what IE considers a circular reference using closures. Several examples are provided in the second link.

In IE6, the only way to reclaim the memory is to terminate the whole process. In IE7 they improved it so that when you navigate away from the page in question (or close it), the memory is reclaimed. In IE8, DOM objects are better understood by JScript and are collected as you'd expect they should be.

The suggested workaround for IE6 (besides terminating the process!) is not to use closures.

Ken Redler
There weren't many answers, so you get the vote. I'm not too worried about IE6 though. According to (http://www.w3schools.com/browsers/browsers_stats.asp), it's still used by 7%, but I figure that will die down dramatically in the coming months. The government is a huge contributor to older versions of IE, once they use the new version, a lot of the private contractors will probably stop supporting/using it as well. I think in the past couple months a lot of govt agencies have switched to a newer, more secure browser, especially after that Adobe/IE6 threat.
vol7ron
I'm a bit surprised at the lack of answers too. I take your point on IE6; but sadly, I still see about 25% IE6 among the visitors to the corporate-focused web applications I work on. Some of these huge businesses are so conservative that they're still milking the "sunk cost" from their Windows XP investment, and IE6 along with it. And they're weighing down, to various degrees, the progressive efforts of web-based vendors who nonetheless still want their business. I really hope it dies down in coming months, but I wouldn't be shocked if there are big businesses still running IE6 in 2015.
Ken Redler
A: 

Closures may cause memory leaks, however Mozilla has made attempts to optimize their garbage collection engine to prevent this.

I'm unsure how Chrome handles closures. I think they're on par with Mozilla, but I don't want to say for sure. IE8 is definitely improved over the earlier versions of IE - it's almost a whole new browser, there are still some nuances.

You should also benchmark the code to see if there's any improvement in speed.

Armando