Actually closures *do* reference every outer variable even when not
used - if they did not, JavaScript's entire lexical scoping principal
would break. Evey invocation of a function establishes and enters a
new execution context. Each  execution context defines a
VariableEnvironment which is a repository for variables declared by
that context. In addition, each VariableEnvironment will reference the
VariableEnvironment of its enclosing context. In this way every
function invocation references - in the form of a hierarchy - the
entire universe of variables to which it has access.

What effect do closures have on memory leaking? Almost impossible to
answer since every JavaScript function in effect forms a closure -
that is how functions reference outer variables including global
variables. Better to not get hung up on closures and memory leaks per
se and instead make the following checks:

1) is my code designed to work in IE7 or older?
2) Does my JavaScript make direct reference to a DOM object?
3) Does that DOM object have any attributes that reference back to my
JavaScript (typically expando properties)

If the answer to any of the above is no then you probably won't suffer
memory leaks - so sit back, relax and take full advantage of
closures ;-)

On Dec 25, 7:32 am, Balázs Galambosi <[email protected]> wrote:
> > Will closure create references to every object outer even when
> > I don't explicitly use them? [...]
> > In this case, I still have a memory leak?
>
> No, if you are not referencing the DOM object than there will be no
> circular reference so no memory leak.
>
> - Balázs
>
> 2010/12/25 Yu-Hsuan Lai <[email protected]>:
>
>
>
> > Will closure create references to every object outer even when I don't
> > explicitly use them?
>
> > example:
> > function outer () {
> >    var div = document.createElement("div");
> >    function inner() {
> >          var a,b,c.... and do something blahblah without div;
> >    }
> >    outer = inner();
> >    return inner;
> > }
>
> > In this case, I still have a memory leak?
>
> > On Sat, Dec 25, 2010 at 10:44 AM, Garrett Smith <[email protected]> 
> > wrote:
> >> On 12/24/10, fernando trasvina <[email protected]> wrote:
>
> >>> On Dec 24, 2010, at 6:43 PM, Garrett Smith wrote:
>
> >>>> On 12/24/10, Michael Haufe (TNO) <[email protected]> wrote:
> >>>>> On Dec 24, 3:05 pm, Garrett Smith <[email protected]> wrote:
>
> >>>>>> I rather have it one way or the other. e.g.
>
> >>>>>>  makePoint(x, y);
>
> >>>>>> - OR -
>
> >>>>>>  new Point(x, y);
>
> >>>>>> I just don't like seeing any extra if/else in the code. I also don't
> >>>>>> want to handle the case where somebody might be relying on an anomaly
> >>>>>> of calling the constructor as a function call.
>
> >>>>> If defensive programming isn't necessary, of course. But since JS
> >>>>> can't statically enforce such things it may be necessary to do so.
>
> >>>> If a factory is used, then that's irrelevant. Toy example:
>
> >>>> function getAPoint(x, y) {
>
> >>>> }
> >>>> The worst the client could do would be to use `new getAPoint`. That
> >>>> would be a problem if the API expects `this` to be global object.
>
> >>>> Methods can be shared in scope, but the x and y properties can be
> >>>> instance properties.
>
> >>>> function getAPoint(x, y) {
> >>>>  function distanceFromOrigin() {
> >>>>    return Math.sqrt((this.x * this.x) + (this.y * this.y));
> >>>>  }
> >>>>  getAPoint = function(x, y) {
> >>>>    return {
> >>>>      x : x,
> >>>>      y : y,
> >>>>      distanceFromOrigin: distanceFromOrigin
> >>>>    };
> >>>>  };
> >>>>  return getAPoint(x, y);
> >>>> }
> >>>> getAPoint(4, 0).distanceFromOrigin();
>
> >>> I would say that coding this way should not be done unless there is an
> >>> extreme requirement for it.
>
> >>>> The downside to that is `distanceFromOrigin` is hanging off the VO, so
> >>>> it looks like a private static method, so what is `this`?
>
> >>>> It might be OK to "leak" a little implementation detail in this case:
>
> >>>> function getAPoint(x, y) {
> >>>>  function Point(x, y) {
> >>>>    this.x = +x;
> >>>>    this.y = +y;
> >>>>  }
> >>>>  Point.prototype = {
> >>>>    distanceFromOrigin : function() {
> >>>>      return Math.sqrt((this.x * this.x) + (this.y * this.y));
> >>>>    }
> >>>>  };
>
> >>>>  getAPoint = function(x, y) {
> >>>>    return new Point(x, y);
> >>>>  };
>
> >>>>  return getAPoint(x, y);
> >>>> }
>
> >>> this should be done this way. you should not be defining the constructor
> >>> function every time you run your factory,
>
> >> You're making a statement about the code that is false. The example
> >> uses a technique that is known as "function rewriting" or "russian
> >> doll" or I've explained it with more elaboration below.
>
> >> this what is
> >>> really doing is creating a new constructor function every time and 
> >>> building
> >>> an instance for it completely useless because because
> >>> then how would you do instanceof? never put this type of closures for
> >>> factories unless really needed.
>
> >> Your conclusion follows your analysis, which unfortunately is
> >> incorrect. Please see my explanation below.
>
> >>> var Point = function(){};
>
> >>> var getAPoint = function(x,y){
> >>>       return new Point(x,y);
> >>> }
>
> >> What's missing from that example?
>
> >> Here is my explanation:
>
> >>>> The Point constructor is cached on the VO of the outer getAPoint.
> >>>> Outer getAPoint identifier gets assigned to inner getAPoint identifier
> >>>> but the scope chain of the inner getAPoint function has the Point
> >>>> constructor and prototype.
>
> >> That's my explanation. VO = "Variable Object".
>
> >> I've added two alerts and some explanatory comments. Generally, I
> >> would not want to see such comments cluttering up the code but I added
> >> them to help explain how the code works.
>
> >> The following example has two alerts: one in the outer "getAPoint"
> >> function and one in the inner function, which is reassigned to
> >> "getAPoint". Only the first call to getAPoint(1, 2); results in the
> >> `getAPoint` function being called. When that getAPoint function is
> >> first called, it reassigns the
>
> >> function getAPoint(x, y) {
> >>  alert('in outer getAPoint');
> >>  function Point(x, y) {
> >>    this.x = +x;
> >>    this.y = +y;
> >>  }
> >>  Point.prototype = {
> >>    distanceFromOrigin : function() {
> >>      return Math.sqrt((this.x * this.x) + (this.y * this.y));
> >>    }
> >>  };
>
> >>  // When this statement is reached,
> >>  // getAPoint is resolved up the scope chain
> >>  // and assigned the value of the FunctionExpression.
> >>  // That FunctionExpression's scope chain has Point on it,
> >>  // and so the Point constructor can still be accessed.
> >>  getAPoint = function(x, y) {
> >>    alert("in inner getAPoint");
> >>    return new Point(x, y);
> >>  };
>
> >>  // This statement is called in the original getAPoint
> >>  // function. That only happens once because the
> >>  // previous statement changed the value of getAPoint
> >>  // to point to the inner function.
> >>  return getAPoint(x, y);
> >>  }
>
> >> getAPoint(4,0); // outer alert, inner alert.
> >> getAPoint(4,0); // inner alert.
>
> >> You can see that the outer function is called only once. The `Point`
> >> constructor function is cached on the scope of the inner function.
> >> That's what we want here.
>
> >> The caveat to this pattern is that you get caching of everything on
> >> the VO automatically. Be careful and set things you don't need to keep
> >> around null. Otherwise, you'll have memory leaks.
>
> >> A common memory leak example is when the outer function creates
> >> elements to perform a feature test, saving those elements on the VO.
> >> Those identifiers are available on the scope chain of any nested
> >> functions. The reference to the element from that identifier can be
> >> broken by assinging those identifiers the value `null`.
>
> >> function outer() {
> >>  var div = document.createElement("div");
> >>  function inner() {
> >>    // alert(div); // Its available on the scope chain
> >>  }
> >>  outer = inner;
> >>  return inner();
> >> }
>
> >> That memory leak of `div` can be fixed by either setting `div` to null
> >> or by declaring `div` inside a function that doesn't expose any nested
> >> functions (so that `div` can be GC'd when that function completes).
>
> >> [snipped signatures]
> >> --
> >> Garrett
>
> >> --
> >> To view archived discussions from the original JSMentors Mailman list: 
> >> http://www.mail-archive.com/[email protected]/
>
> >> To search via a non-Google archive, visit 
> >> here:http://www.mail-archive.com/[email protected]/
>
> >> To unsubscribe from this group, send email to
> >> [email protected]
>
> > --
> > Lai, Yu-Hsuan
>
> > --
> > To view archived discussions from the original JSMentors Mailman list: 
> > http://www.mail-archive.com/[email protected]/
>
> > To search via a non-Google archive, visit 
> > here:http://www.mail-archive.com/[email protected]/
>
> > To unsubscribe from this group, send email to
> > [email protected]

-- 
To view archived discussions from the original JSMentors Mailman list: 
http://www.mail-archive.com/[email protected]/

To search via a non-Google archive, visit here: 
http://www.mail-archive.com/[email protected]/

To unsubscribe from this group, send email to
[email protected]

Reply via email to