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]

Reply via email to