> 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