Prev: FAQ Entry Proposal: What is (function(){ /*...*/ })() ?
Next: FAQ Topic - What is Ajax? (2010-03-01)
From: David Mark on 9 Mar 2010 04:51 Andrea Giammarchi wrote: > On Mar 8, 1:55 pm, David Mark <dmark.cins...(a)gmail.com> wrote: >> Then why are you checking for null? That's the point. > > again, to know if a variable is null or undefined since I threat both > values as one, And therein lies the rub. > I've never had a valid reason for distinguish between > null and undefined. Unfortunately, the rest of the JS world, including host objects disagrees with your assessment of the two values. Therefore, your code is unintelligible to others. > > >> Your code is >> ambiguous and the next person reading it can't be expected to read your >> mind, so will have to investigate to determine exactly what you meant >> (or did not mean). > > since you'll never find a === undefined in my code, I wonder wchih > part is ambiguous... The part that is not === undefined, of course. In other words the == null parts. > > >> What does that mean? > > typo, I meant every time I have to specify via *comment* that I meant > it ... > > >> That's not the point. I know what it means, but I can't guess what >> _you_ thought it meant. If I find, after investigation, that you were >> using == null when === undefined would have sufficed > > there we are ... > === undefined is a disaster prone approach. Nobody should rely in a > global scope variable as undefined is to understand if a variable is > undefined. That's beside the point. Use typeof xyz == 'undefined' if you are worried about the global undefined being stepped on (or compatibility issues that can arise in ancient browsers). > typeof varname === "undefined" is the only safe way, OR we can simply > test against == null if we are NOT interested into undefined values. Those two are not equivalent, hence the ambiguity. > > >> You have got the wrong end of the stick (again). > > while apparently You have not get what is the problem and why ... > [...] No, I get what the problem is. :)
From: Richard Cornford on 14 Mar 2010 22:34 On Mar 5, 1:37 pm, Scott Sauyet wrote: > Richard Cornford wrote: >> On Mar 4, 6:02 pm, Scott Sauyet wrote: >>> On Mar 4, 11:37 am, Richard Cornford wrote: >>>> On Mar 4, 4:28 pm, Scott Sauyet wrote: <snip> >>> Sorry, I didn't realize the it was a members-only group. The >>> new jQuery forums seem to me a huge step backwards from a >>> plain mailing list. > >> Certainly restricting the reading of the content seems odd >> (perhaps there is money to be made from the user database so >> it is advantageous to force as many registrations as possible). > > Although I suppose that could make sense, it seems to be the least > popular areas that require registration. It appears that this area (so I presume much else besides) is now public, which seems like a good idea. <snip> > I kept wondering if there was something that the author was > forgetting to include in his write-up, but the more I think about > it, the less I believe that he had created anything useful, all his > talk about "This is a pattern I first developed for my own needs, > and now has found its way into Fortune 500 companies," > notwithstanding. > >> I am glad that someone questioned this in a context that the >> author would find hard to dismiss/ignore, but was there any >> response? I assume that there was not. > > Absolutely none. My response was a week ago, and there has > been no other activity in the thread. It seems from this:- <URL: http://forum.jquery.com/topic/adamovsky-s-new-design-pattern-issues > - that your response, suggesting that the 'pattern' proposed would not work as advertised was insufficiently strongly worded, as it has not proved enough to prevent people from trying it out and finding that it doesn't work the hard way. Sometimes there is something to be said for plain talking, even if some people get offended by it. <snip> > I was trying to find a way to do what the author seemed to want, > and haven't found anything very useful. That is an entirely understandable goal, in context. However, it is worth remembering where it is that the motivation comes from. It is a consequence of method chaining, as generally employed in JQuery. I found method chaining an appealing idea when I was first made aware of the possibility. I then tried it out, and abandoned it within a couple of weeks. There were two reasons for my abandoning it; the first being that it made debugging considerably harder (precluding the 'simple' debugging techniques available in web browsers and forcing a shift to full-on debugger software (which wasn't as widely available as it is now, and not available for many browsers in any form at the time (while today it is only not available for (some/many?) smaller 'embedded' browsers))), and it made keeping track of the types of the objects in use very difficult, and so rendered code harder to understand. That second reason, keeping track of the types of objects, becomes a problems when you start designing many types of objects to use method chaining, and start to have methods of one type of object return objects of other types, on which you immediately call (possibly chains of) methods. Given that OO design applied to any substantial system will tend to necessitate (or at least indicate) numerous distinct types of object, I concluded that it would be better to design such systems without method chaining. And if you can't build big systems using that strategy I concluded that it would be better to never use it. Obviously some alternative possibilities exist, and one of those is for the design not to involve the creation of multiple types of objects but to instead create one 'super' (not in the normal OO sense) type that has all of the methods and properties needed by all of possible types that would be used otherwise. This would be a design where the omitted types were conceived as interfaces, but instead of having distinct objects implement those interfaces, each interface was added to that single type, making it the 'super' type. Then as the methods chain there is no longer any problem keeping track of the types of the objects being acted upon, as they are always that one single 'super' type. This is the approach taken by JQuery and its plugins. You avoid the possible issues of keeping track of the type of object through the chains of method calls because all of the objects are of the JQuery type. I didn't seriously consider this strategy for myself because it is pretty obvious that there are practical limits on how big (how many interfaces) any single object can implement. Sooner or later there are going to be naming collocations, and to avoid that some pretty restrictive naming conventions or something equally anti-intuitive is going to be necessary. Then there was the question of whether the resulting objects made any sense, and the impact of that on the understandably of code if they did not. Why should an object that was a collection of, say, LI elements (or even any arbitrary collection of elements) have table sorting methods? So given the debugging issue on top, I decided that method chaining provided nothing that would even come close to mitigating its cost. However, once you are using JQuery, and so have the 'super' object, you are going ot need something approaching 'namespacing' to avoid the naming collisions, and you are going to want to be preserving the 'super' object through any and all chains of method calls. And thus you (and presumably numerous others, who get to the level of wanting to create their own plugins) come to your question. > Forgetting the specifics > of JQuery, can anyone suggest a useful way of defining a namespace > for additional functions on the prototype of a constructor > function so that those additional functions will be called in the > context of the object created by the constructor? You mean with the - this - value referring to an instance of the type of object created with the constructor? The problem being that javascript sets the - this - value based on how a function is called at the moment of calling it. > Perhaps that's a little dense. :-) > > If I have a constructor, > > function MyWidget() { /* ... */} > > and a simple plugin architecture: > > MyWidget.prototype.myPlugin = function() { > // here "this" is the object created by 'new MyWidget()' > } > > Is there a straightforward way to create a plug-in namespace for > some related functionality so that the object constructed is the > context object for calls to the namespaced methods? > > // MyWidget.prototype.namespace = ??? > > var widget = new MyWidget(); > widget.namespace.method1() { > // "this" should be a reference to the widget created. That is only going to happen if - widget - and - widget.namespace - refer to the same object (at least in ES3), which defeats the purpose of the exercise as then - widget - has the - method1 - method, and no useful namespacing is going on. > } > > Obviously, it wouldn't be hard to do something that worked like this: > > widget.namespace().method1() <snip> > But that doesn't feel quite right. I'd really rather have > > widget.namespace.method1() With getters for properties (i.e. ES 5) the latter can behave like the former. Though that is nothing more than hiding the method call in the former so isn't much of a step forward. > But I can't think of a way to do this. Any suggestions? Avoid trying to stuff everything into a single object type, and so avoid method chaining so you have some hope of keeping track of the types of objects you are then using. Richard.
From: Richard Cornford on 14 Mar 2010 22:34
On Mar 5, 3:01 pm, Scott Sauyet wrote: > Richard Cornford wrote: >> On Mar 4, 4:28 pm, Scott Sauyet wrote: >>> Richard Cornford wrote: >>> It's possible that this is the case. But my take is that >>> the quality of JS found around the web is better than it >>> was before the onset of the GP libraries. > >> While my impression is that it is about the same. > >>> There are still plenty of really poor scripts floating >>> around (and I'm talking about ones that make jQuery et al >>> look positively brilliant) > >> What about the really poor scripts that use JQuery et al? > >>> but they no longer get the exposure they used to, as it's >>> become so easy to achieve what these sometimes massive >>> one-off scripts did using only line or two of jQuery-based >>> code. (Dojo, MooTools, YUI, whatever.) > >> The "massive" one-of scripts you refer to (at least the better >> of them) tended to be designed to be copied into a web page and >> then given a "line or two" of configuration. There is not that >> much difference between doing that and using a general purpose >> library, except that the one-off script likely did not contain >> much that it did not use, but the general purpose library will >> contain some that is not used in any equivalent task. > > I wish I could remember its name, but I remember having to remove > a 150K animation script from a site. All it did was animate > positions and sizes. It was littered with "if (document.layers)" > and "if (document.all)", That suggests an old script, and possibly a script pre-dating the W3C DOM. > and worse, it required the user to add > those same guards to sections of their own code. There were two very distinct browser object models in use in the version 4 browser era. The degree to which things could be abstracted/normalised between the two was limited, and while it was possible with animation (to the extent that animation was supported at all (as pre-Opera 7 Opera versions were never that dynamic) there were plenty of people authoring this stuff who did not think it was worth the effort (to do, or to learn how to do). > It was easy > enough to replace with a small custom script, and it was replaced > at a time when the client didn't care about the version 4 browsers, > so the code was reasonably clean. But what I remember most about > it was that this was a *popular* script. "Popular" had never been any sort of guarantee of quality. But I don't think you have spent enough time looking at the internal details of the current set of 'popular' libraries. There is still plenty of branching for individual browsers going on, just driven by different criteria. For example, form Dojo (version 0.9):- | dojo.io.iframe = { | create: function(/*String*/fname,/*String*/onloadstr,/*String?*/uri){ | //summary: Creates a hidden iframe in the page. Used mostly | // for IO transports. | // You do not need to call this to start a dojo.io.iframe | // request. Just call send(). | //fname: String | // The name of the iframe. Used for the name attribute on | // the iframe. | //onloadstr: String | // A string of JavaScript that will be executed when the | // content in the iframe loads. | //uri: String | // The value of the src attribute on the iframe element. | // If a value is not | // given, then dojo/resources/blank.html will be used. | if(window[fname]){ return window[fname]; } | if(window.frames[fname]){ return window.frames[fname]; } | var cframe = null; | var turi = uri; | if(!turi){ | if(djConfig["useXDomain"] && !djConfig["dojoBlankHtmlUrl"]){ | console.debug("dojo.io.iframe.create: When using cross-domain " | +"Dojo builds," | + " please save dojo/resources/blank.html to your domain " | + "and set djConfig.dojoBlankHtmlUrl" | + " to the path on your domain to blank.html"); | } | turi = ( | djConfig["dojoBlankHtmlUrl"]|| | dojo.moduleUrl("dojo", "resources/blank.html") | ); | } | var ifrstr = dojo.isIE ? | '<iframe name="'+fname+'" src="'+turi+'" onload="'+onloadstr+'">' | : 'iframe'; | cframe = dojo.doc.createElement(ifrstr); | with(cframe){ | name = fname; | setAttribute("name", fname); | id = fname; | } | dojo.body().appendChild(cframe); | window[fname] = cframe; | | with(cframe.style){ | if(!dojo.isSafari){ | //We can't change the src in Safari 2.0.3 if absolute | // position. Bizarro. | position = "absolute"; | } | left = top = "0px"; | height = width = "1px"; | visibility = "hidden"; | } | | if(!dojo.isIE){ | this.setSrc(cframe, turi, true); | cframe.onload = new Function(onloadstr); | } | | return cframe; | }, | setSrc:function(/*DOMNode*/iframe,/*String*/src,/*Boolean*/replace){ | //summary: | // Sets the URL that is loaded in an IFrame. The replace | // parameter indicates whether | // location.replace() should be used when changing the | // location of the iframe. | try{ | if(!replace){ | if(dojo.isSafari){ | iframe.location = src; | }else{ | frames[iframe.name].location = src; | } | }else{ | // Fun with DOM 0 incompatibilities! | var idoc; | if(dojo.isIE){ | idoc = iframe.contentWindow.document; | }else if(dojo.isSafari){ | idoc = iframe.document; | }else{ // if(d.isMozilla){ | idoc = iframe.contentWindow; | } | | //For Safari (at least 2.0.3) and Opera, if the iframe | //has just been created but it doesn't have content | //yet, then iframe.document may be null. In that case, | //use iframe.location and return. | if(!idoc){ | iframe.location = src; | return; | }else{ | idoc.location.replace(src); | } | } | }catch(e){ | console.debug("dojo.io.iframe.setSrc: ", e); | } | }, There is still plenty of branching for - isIE -, - isSafari -, and so on. And most of it unnecessary. > I simply haven't seen that sort of thing with the GP libraries. > I've seen plenty of new gratuitous use of animations in pages > because they already include, say, dojo, and it's so easy to > just add an animation now. But I haven't seen the kind of > nonsense that requires a new release of the script on every point > release of a browser. You have not been watching the introduction of new IE versions then. > One might not like the APIs provided by these GP libraries, but > they do usually provide APIs straightforward enough that the code > that uses them is simple to write and comprehend. Simple to write perhaps. Comprehension pretty much pre-supposes familiarity with the library being used as they frequently employ terse method names that do little to put across the actions/purposes of those methods. That is, the resulting code is a long way from being self-documenting. > In many site, > the worst problem of code using JQuery is often the relatively > innocuous failure to cache the JQuery objects created, running > queries over and over. A combination of a failure to understand what is actually happening behind the scenes and a construct that is trivial to write. > I'm not trying to say there is no bad code written by users of GP > libraries. There is certainly some horrendous stuff. But I'm > seeing much less awful code today than five years ago. While I just see the nature of the bad code changing. >> I do see libraries such as JQuery superseding the copy-n-paste >> script collections of the past, but only in that they provide >> the equivalent; a source of example code that people who don't >> know what they are doing can copy and paste into their own pages, >> achieve a 'working' outcome, and elaborate through repletion. >> Indeed, I see that as the > > "elaborate through repletion"? Yes, this (unfortunately, but necessarily long) example, culled from the old JQuery Google group, illustrates what I mean:- | jQuery.noConflict(); | jQuery(document).ready(function(){ | jQuery('#loading').show(); | jQuery('.wrap').slideDown(1000); | jQuery('#loading'-).fadeOut(1500, setTimeout('showdocs()',1500)); | jQuery("a:contains('Home')").click(function(e){ | e.preventDefault(); | link = jQuery(this).attr('href'); | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600, function(){ | setTimeout('window.location = link',1000); | }); | }); | jQuery("a:contains('Pages')").click(function(e){ | e.preventDefault(); | link = jQuery(this).attr('href'); | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600, function(){ | setTimeout('window.location = link',1000); | }); | }); | jQuery("a:contains('Gallery')").click(function(e){ | e.preventDefault(); | link = jQuery(this).attr('href'); | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600, function(){ | setTimeout('window.location = link',1000); | }); | }); | jQuery("a:contains('Contact')").click(function(e){ | e.preventDefault(); | link = jQuery(this).attr('href'); | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600, function(){ | setTimeout('window.location = link',1000); | }); | }); | jQuery("a:contains('Website')").click(function(e){ | e.preventDefault(); | link = jQuery(this).attr('href'); | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600, function(){ | setTimeout('window.location = link',1000); | }); | }); | jQuery("a:contains('Statistics')").click(function(e){ | e.preventDefault(); | link = jQuery(this).attr('href'); | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600, function(){ | setTimeout('window.location = link',1000); | }); | }); | jQuery("a:contains('Help')").click(function(e){ | e.preventDefault(); | link = jQuery(this).attr('href'); | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600, function(){ | setTimeout('window.location = link',1000); | }); | }); | jQuery("a:contains('Edit')").click(function(e){ | e.preventDefault(); | link = jQuery(this).attr('href'); | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600, function(){ | setTimeout('window.location = link',1000); | }); | }); | jQuery("a:contains('Return to')").click(function(e){ | e.preventDefault(); | link = jQuery(this).attr('href'); | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600, function(){ | setTimeout('window.location = link',1000); | }); | }); | jQuery("a:contains('Add')").click(function(e){ | e.preventDefault(); | link = jQuery(this).attr('href'); | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600, function(){ | setTimeout('window.location = link',1000); | }); | }); | jQuery('#jqueryform').submit(function(){ | jQuery('#loading').fadeIn(200); | jQuery('.wrap').slideUp(600); | }); | }); | function showdocs() { | jQuery('.docs').fadeIn(1500); | } You can see the code of someone who has been shown how to achieve an effect they wanted (badly, but what is new there), has taken that starting point and elaborated on it to achieve the same effect in a number of places, and done so by repeating the original with minor changes. This individual has no idea of programming, else we would not see 10 (or is it 20, given the - slideUp - callback) identical function expression definitions in their code. >> best (if not the only) way in which any new library will achieve >> 'popularity'. Technical quality will always be largely irrelevant >> (so long is it isn't so bad that it is obviously non-functional >> on common browsers) because the people looking for a 'solution' >> to their problem cannot judge that aspect, while the (relative) >> ease of pasting an example into a working context is something >> that can easily be judged. > > I'm trying to figure out what it is about the Web that makes > this problem so much more severe than in other development > environments. It certainly seems to be so. Ease of use trumps > other measure of quality all the time in web development. Any > thoughts on why? Yes, lots. >> [ ... ] I was thinking in terms of >> people's perceptions of their own abilities. I have observed >> before that early superficial success (often following earlier >> frustration) with the language seems to result in a quite >> unjustified overconfidence in ones own abilities, and that >> while suffering that overconfidence it becomes difficult to >> learn/advance [ ... ] > > And, as you say, this becomes especially problematic if people > so stuck become influential. > > There is of course a large spectrum of ability in almost any > field of endeavor. But not so much in specialised fields. For example; astronauts, are either pretty good at it or they are not astronauts. Surgeons also spring to mind. An ex-girlfriend of a friend of mine once complained to me that it was unreasonable that she had been thrown out of medical school for failing to achieve the required 95% pass rate in her assessments. It is less unreasonable from the patient's point of view, when you realise that apparently it is acceptable for doctors to be wrong 5% of the time, and they would not be wanting to see that percentage increase. > With web technologies, including JS, it does seem that at > lot more people without particularly advanced skills do see > themselves as extremely knowledgeable. Perhaps its the > number of amateurs involved. That will be a factor. But possibly as much in how those armatures react to the people who know more than them. You don't have to know that much to seriously impress those who know less, but having impressed them you would only be fooling yourself to take their accolades seriously. > There aren't that many people > who aren't professional programmers or academics trying to > implement a tricky cryptography algorithm in C++. But the > church's website might well be entirely maintained by > someone who learned most of their web technologies by > cutting and pasting from sties they like. > > And even those of us who are professional are not > necessarily as advanced as we might like. I personally > have become involved with c.l.j.s. because I know that I > was missing some fundamentals. For my last few positions, > I've been the go-to-guy on the team for JS issues. In > some cases, I could come up with working solutions to > problems even though I didn't understand all of the > underlying principles thoroughly. I figured that here, > I would be able to contribute and learn at the same time. > > For those people who think they're beyond that, the only > hope I have is that they'll be jolted out of their > complacency when they actually do get in over their heads > and somebody shows how much they still have to learn. You can hope. People who are in over their heads often resort to just doing things badly rather than acquiring the extra depth. >>> Of course [GP library users trying to advance will] have >>> unlearning to do. But most advancement involves some >>> degree of unlearning. > >> But what if the things that they unlearn include the >> opinion that starting out using a general purpose >> liberally was a good idea? > > :-) > > They might. That's a harsher lesson than they might be > ready for, but if it really is the case, presumably they'll > eventually learn it as they advance. <snip> Eventually yes. After all, if this position is viable any reasoning and inquisitive individual will eventually see it. And as we watch the general purpose libraries change over time we see the paths they take do lead in this general direction. Richard. |