> 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 <rainco...@gmail.com>:
> 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 <dhtmlkitc...@gmail.com> 
> wrote:
>> On 12/24/10, fernando trasvina <trasv...@gmail.com> wrote:
>>>
>>> On Dec 24, 2010, at 6:43 PM, Garrett Smith wrote:
>>>
>>>> On 12/24/10, Michael Haufe (TNO) <t...@thenewobjective.com> wrote:
>>>>> On Dec 24, 3:05 pm, Garrett Smith <dhtmlkitc...@gmail.com> 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/jsmentors@jsmentors.com/
>>
>> To search via a non-Google archive, visit here: 
>> http://www.mail-archive.com/jsmentors@googlegroups.com/
>>
>> To unsubscribe from this group, send email to
>> jsmentors+unsubscr...@googlegroups.com
>>
>
>
>
> --
> Lai, Yu-Hsuan
>
> --
> To view archived discussions from the original JSMentors Mailman list: 
> http://www.mail-archive.com/jsmentors@jsmentors.com/
>
> To search via a non-Google archive, visit here: 
> http://www.mail-archive.com/jsmentors@googlegroups.com/
>
> To unsubscribe from this group, send email to
> jsmentors+unsubscr...@googlegroups.com
>

-- 
To view archived discussions from the original JSMentors Mailman list: 
http://www.mail-archive.com/jsmentors@jsmentors.com/

To search via a non-Google archive, visit here: 
http://www.mail-archive.com/jsmentors@googlegroups.com/

To unsubscribe from this group, send email to
jsmentors+unsubscr...@googlegroups.com

Reply via email to