Prev: capture external js filename
Next: Dynamically refresh (update) JSP webpage when JMS notification is received
From: Scott Sauyet on 2 Feb 2010 15:56 What techniques to people use to hide implementation details in shared code, especially to keep helper variables reasonably private? Several threads on FAQ questions had me randomly reading the FAQ, and the entry on checking for an open child window [1] made me pause. The suggestion not to use pop-ups is fine, and there is nothing exactly wrong with the code. But it introduces a global variable as well as the function. This might well be what's wanted here, but often it's just unwanted clutter, and I'm wondering what suggestions the experts here have to avoid such clutter. For example, the following adds the unwanted global "count": var count = 0; function test() { alert("#" + (++count) + " run at " + new Date()); } There are several ways to deal with that. I often use a closure: var test = (function() { var count = 0; return function() { alert("#" + (++count) + " run at " + new Date()); } })(); Or we could make "count" a property of the function: function test() { test.count = test.count || 0; alert("#" + (++test.count) + " run at " + new Date()); } I know that there are performance concerns having to do with the overuse of closures, but I don't really know any details. Obviously that is an argument against the first technique. Another argument against it is the additional syntactic complexity. But the closure technique also has the advantage that the implementation doesn't leak at all, whereas in the other one, the implementation is exposed and could be manipulated by malicious or clueless use, via, say: test.count = 42; Obviously, in many situations that is simply not an issue. ("Doc, it hurts when I do *this*." "So don't do that!") But when writing reusable code for a wide user base, it might be at least one consideration. There are also OO techniques to handle this such as this: function Thingy() { this.count = 0; } Thingy.prototype.test = function() { alert("#" + (++test.count) + " run at " + new Date()); } var thingy = new Thingy(); But this is no longer a drop-in replacement for the original function, and it requires the object "thingy" in the global scope. And sometimes, there's the stupid problem of simply not having a good noun (hence "Thingy"); this can actually be an important consideration to me. In general, unless I'm already coding all my relevant script in an OO manner, this holds little appeal. Are there others for whom this is obviously the best solution? So how do you choose between these methods, or what other techniques do you use to keep your implementation details hidden and especially keep helper variables out of the global scope? -- Scott ______________________ [1] Section 9.4 <http://jibbering.com/faq/#isWindowOpen>
From: Evertjan. on 2 Feb 2010 16:32 Scott Sauyet wrote on 02 feb 2010 in comp.lang.javascript: > var test = (function() { > var count = 0; > return function() { > alert("#" + (++count) + " run at " + new Date()); > } > })(); KISS: function test() { alert("#1 run at " + new Date()); }; -- Evertjan. The Netherlands. (Please change the x'es to dots in my emailaddress)
From: Scott Sauyet on 2 Feb 2010 16:43 On Feb 2, 4:32 pm, "Evertjan." <exjxw.hannivo...(a)interxnl.net> wrote: > Scott Sauyet wrote on 02 feb 2010 in comp.lang.javascript: > >> var test = (function() { >> var count = 0; >> return function() { >> alert("#" + (++count) + " run at " + new Date()); >> } >> })(); > > KISS: > > function test() { > alert("#1 run at " + new Date()); > > }; And the second time you call it?... -- Scott
From: Garrett Smith on 2 Feb 2010 17:13 Scott Sauyet wrote: > What techniques to people use to hide implementation details in shared > code, especially to keep helper variables reasonably private? > All Function objects have a scope chain. Based on the code examples below, you already knew that. > Several threads on FAQ questions had me randomly reading the FAQ, and > the entry on checking for an open child window [1] made me pause. The > suggestion not to use pop-ups is fine, and there is nothing exactly > wrong with the code. But it introduces a global variable as well as > the function. This might well be what's wanted here, but often it's > just unwanted clutter, and I'm wondering what suggestions the experts > here have to avoid such clutter. > Function rewriting? var openWin = function(aURL) { var myWin; return (openWin = function(aURL) { if (!myWin || myWin.closed ) { return window.open(aURL,'myWin'); } else { myWin.location.href = aURL; myWin.focus(); return myWin; } })(aURL); }; openWin("http://example.com"); > For example, the following adds the unwanted global "count": [snip example] > > There are several ways to deal with that. I often use a closure: > [snip example] There you go. > Or we could make "count" a property of the function: > > function test() { > test.count = test.count || 0; > alert("#" + (++test.count) + " run at " + new Date()); > } > > I know that there are performance concerns having to do with the > overuse of closures, but I don't really know any details. Obviously > that is an argument against the first technique. Another argument > against it is the additional syntactic complexity. > Scope Chain and Identifier Resolution in ECMA-262 clearly states what the observable behavior is. In most cases, closures help performance. This is going to be even more true in future releases of Tracemonkey. https://bugzilla.mozilla.org/show_bug.cgi?id=517164 Tracemonkey has optimized global access, so global access is a bit faster for now. Closure access is generally faster than global access. Closure access is almost always faster than property access. http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/566395fc193eb4f1/1120d91202f005cd?show_docid=1120d91202f005cd&fwc=2 In most implementations, accessing a global property up a long scope chain will be slower than accessing off the containing scope. Accessing the global `test` property, then resolving the `count` property is more involved than resolving a `count` property in containing scope. An added benefit to hidden identifiers is munging. An optimizer such as YUI Compressor will rename a private `longMeaningfulIdentifier` to `B`, for example. > But the closure technique also has the advantage that the > implementation doesn't leak at all, whereas in the other one, the > implementation is exposed and could be manipulated by malicious or > clueless use, via, say: > > test.count = 42; > Right. The problem with that is that it makes it harder to change. If the interface does not expose a count property, then renaming that hidden identifier can be a self-contained change. > Obviously, in many situations that is simply not an issue. ("Doc, it > hurts when I do *this*." "So don't do that!") But when writing > reusable code for a wide user base, it might be at least one > consideration. > When writing code for your own use later, it can be a consideration. By defining a simple interface, it is clearer what variables are public and which are hidden. > There are also OO techniques to handle this such as this: > > function Thingy() { > this.count = 0; > } > Thingy.prototype.test = function() { > alert("#" + (++test.count) + " run at " + new Date()); > } > var thingy = new Thingy(); > > But this is no longer a drop-in replacement for the original function, > and it requires the object "thingy" in the global scope. Identifier `thingy` can be restricted and used in a closure, too. (function(){ var thingy = new Thingy(); })(); -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Evertjan. on 2 Feb 2010 17:17 Scott Sauyet wrote on 02 feb 2010 in comp.lang.javascript: > On Feb 2, 4:32�pm, "Evertjan." <exjxw.hannivo...(a)interxnl.net> wrote: >> Scott Sauyet wrote on 02 feb 2010 in comp.lang.javascript: >> >>> � �var test = (function() { >>> � � � � var count = 0; >>> � � � � return function() { >>> � � � � � � alert("#" + (++count) + " run at " + new Date()) > ; >>> � � � � } >>> � � })(); >> >> KISS: >> >> function test() { >> � alert("#1 run at " + new Date()); >> >> }; > > And the second time you call it?... You are right. -- Evertjan. The Netherlands. (Please change the x'es to dots in my emailaddress)
|
Next
|
Last
Pages: 1 2 3 4 Prev: capture external js filename Next: Dynamically refresh (update) JSP webpage when JMS notification is received |