On Wed, Dec 2, 2009 at 5:26 PM, Mike Samuel <[email protected]> wrote:
> What is the goal of namespaces? > To prevent one module from (unintentionally|intentionally|both) > clobbering an API exported by another module? I'm not sure using "modules" is the correct term in this context. However, the goal of JavaScript "namespacing" as I see it is to prevent one section of code from unintentionally clobbering another section of code, due to naming collisions. This could be combinations of code from one or more developers, organizations, or products. Imagine a typical, modern web page. Consider http://www.mozilla.org. It appears quite clean with only 4 *.js files loaded: mozilla.org.js, jquery-1.3.2.min.js, jquery-ui-1.7.2.custom.min.js, and urchin.js (older version of Google analytics). The first 3 are already very well behaved, actually following the exact standard I'm proposing with nested namespaces, including: jQuery jQuery.ui jQuery.ui.mouse jQuery.event (many other jQuery objects) org.mozilla.carousel org.mozilla.strings org.mozilla.augmentCommunityHovers org.mozilla.init org.mozilla.tabSwitch (other org.mozilla.*) I'd actually prefer that "jQuery" was "com.jquery", but it is certainly an effort towards namespacing. For both jQuery.* and org.mozilla.*, my proposed namespace function could be used to help create these nested objects. Currently, each script needs to find a way to do this itself, or depend upon another library that provides an appropriate namespacing function. Mozilla's is: /** * Namespace */ if (typeof org == 'undefined') { var org = {}; } org.mozilla = function() { /* ... */ } With my proposed addition, this would simply be: namespace("org").mozilla = function() { /* ... */ } or even shorter: namespace("org.mozilla").init = function() { /* ... */ } urchin.js, on the other hand, could certainly use some better namespacing. The only convention used is that everything begins with "_u". There's no standard or anything else to discourage any other of many, many other JavaScript developers to also develop a common library that is prefixed with "_u". Furthermore, as this method of "namespacing" is not using nested objects, it is contributing towards global namespace pollution (http://www.yuiblog.com/blog/2006/06/01/global-domination/ , http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html ). http://mankz.com/code/GlobalCheck.htm shows Google Urchin as having 76 global variables, with 73 in the current version hosted at mozilla.org. Fortunately, Google seems to have paid attention to this, as their newer version (ga.js) places everything as a child of "_gat" (Google AnalyTics?). Again, I would have preferred something like "com.google.analytics", but this is definitely a significant improvement from before. ga.js is quite obfuscated, but it is clear that they are also using nested objects to achieve proper namespacing. As part of this, they are surely having to create these nestings someplace themselves, and could also benefit from the global namespace function that I am proposing. This is not only an issue with web pages, but other products where JavaScript may be mashed together. This includes - but is not limited to - Mozilla Firefox and its extensions, as mentioned in the previously linked https://addons.mozilla.org/en-US/developers/docs/policies/reviews . > What is a namespace? > An object that can be consistently addressed by a dotted path after first > read? > A chain of property names starting from a container that should always > return the same result after first read? For a general definition of a namespace, I'll defer to Wikipedia: http://en.wikipedia.org/wiki/Namespace_%28computer_science%29 . (This also happens to list a number of drawbacks against using the "prefix namespacing" approach as a work-around, mentioned at http://peter.michaux.ca/articles/javascript-namespacing .) In JavaScript, it seems that I and many others (including the above examples of mozilla.org, jQuery, and Google Analytics) agree that namespacing is best accomplished using nested objects, or a "dotted path" as you mentioned. There just isn't anything (yet) built-in to the language to support this beneficial practice. I would contend that namespaces are, and should be dynamic - so that they do not always have to return the same result after the first read. I'm not saying that doing so is a bad practice, but I don't see any reason to introduce artificial limitations to prevent doing so. Also, as being discussed, a namespace in JavaScript really isn't anything special - it is one or more objects. "com.example.x.y.z" could hold a value, as well as acting as a namespace for other child namespaces or values. Again, I'm not stating that this is a good practice, but I don't see a need to prevent it. > Why is namespace not in a namespace? Because the namespace function should be one of few that are "truly global", along with the likes of "eval", and global objects such as "Array" and "String". (Other global functions include (encode/decode)URI(Component), is(Finite/NaN), and parse(Float/Int). It could be argued that these should belong in a namespace, e.g. Math.* for the later ones.) The namespace function should also be used to create the namespace that the namespace function would reside in - which quickly turns into a paradox. > From your blog: > > In what sense are namespaces object-oriented? As I understand the > term, object-orientation is a way of organizing a program around > objects that exchange messages. There's nothing in this proposal that > deals with messaging or objects -- it seems to be a hierarchical > addressing scheme. Maybe a better way to state this is that the proposed method of namespacing in JavaScript makes use of its OO support, namely objects supporting child properties and methods. > When you talk about namespace aliasing, should namespaces be treated > as first class? If namespaces are aliasable, should they be marked > unconfigurable to prevent property deletion or is that up to the > namespace user? Again, namespacing isn't anything "new", and is already being widely used as shown in examples above. I'm just proposing the addition of a global namespace function to make creating new namespaces easier and standardized. The way they are currently being implemented is just through nested objects. I'd say that objects already are (or should be) considered "first class" in JavaScript, so namespaces should be as well. I would say that namespaces should definitely not be marked "unconfigurable". A good JavaScript library, if it has nothing else to do and no more purpose, should actually remove itself from memory, and allow itself to be garbage collected. I don't see any reason to introduce any barriers to allowing this. > When you talk about using the "with" statement with namespaces, what > problem are you trying to solve? Is this meant to act as a poor-man's > java import? > Are you aware of the forward-compatibility problems that "with" > entails, and the effect it has on tools like YUI compressor, closure > compiler, etc.? I wasn't trying to solve any problem. I only mentioned this as an alternative, to show the benefits that the nested-object approach has for namespacing. I agree, the "with" statement probably causes more problems than it helps. ( http://www.yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/ ) While I didn't show an actual example on my blog post, I did mention that the previous example would be better done within another function. Here is correcting that. This: with(com.ziesemer.myPackage){ name = 'Mark'; location = 'Wausau, WI'; alertHello(); } would better be accomplished as something like: (function(){ var czmp = com.ziesemer.myPackage; czmp.name = 'Mark'; czmp.location = 'Wausau, WI'; czmp.alertHello(); })(); > You mention java packages, which provide namespacing, and information > hiding. Is it a goal for this scheme to extend to support information > hiding as well? If so, how? I would not easily agree that Java packages provide information hiding - though the definition of the term "hiding" is up for dispute. Java namespaces allow for organization, and help to prevent naming collisions. Java adds some extra features based on these namespaces, such as package access protection. There would be nothing to prevent JavaScript from adding something similar someday. I guess I would consider the "private" and "protected" keywords more suited to "hiding" things than packages. Even then, these keywords are seldom misunderstood, and should never be used for "security". A little reflection can go a long way! > cheers, > mike (I've used the term "JavaScript" throughout this reply. Really, I think JavaScript and ECMAScript could have been used interchangeably.) -- Mark A. Ziesemer www.ziesemer.com _______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

