Prev: A practical exercise: fighting maskons
Next: FAQ Topic - How do I get a jsp/php variable into client-side javascript? (2009-11-10)
From: David Mark on 10 Nov 2009 00:26 On Nov 9, 11:38 pm, kangax <kan...(a)gmail.com> wrote: > David Mark wrote: > > On Nov 9, 6:27 pm, kangax <kan...(a)gmail.com> wrote: > >> David Mark wrote: > >>> On Nov 9, 3:41 pm, Asen Bozhilov <asen.bozhi...(a)gmail.com> wrote: > >>>> I read ajaxian.com. There i found one post which presented one new > >>>> JavaScript framework. The name of the framework is call "Underscore".. > >>>> <URL:http://documentcloud.github.com/underscore/> > >>>> | Underscore is a utility-belt library for JavaScript that provides > >>>> | a lot of the functional programming support that you would > >>>> | expect in Prototype.js (or Ruby), > >>>> | but without extending any of the built-in JavaScript objects. It's > >>>> the tie to go along with jQuery's tux. > >>>> This is the first sentence in the page, that page must be > >>>> documentation of framework. I don't like style like this. When you > >>>> created framework, lived alone another framework. They have own > >>>> problems and own advantages. However, if anybody want to see source > >>>> code of "Underscore": > >>>> <URL:http://documentcloud.github.com/underscore/underscore.js> > >> [...] > [...] > >>> // Create a (shallow-cloned) duplicate of an object. > >>> _.clone = function(obj) { > >>> if (_.isArray(obj)) return obj.slice(0); > >>> return _.extend({}, obj); > >>> }; > >>> Prototypian (i.e. backwards approach to inheritance). > >> What are you talking about? Prototype always used Lasse's clone/inherit > >> -like approach. > > > As to this loop, perhaps I am thinking of another library (or more > > than one likely). But ISTM "extend" was part of Prototype's > > implementation of classical inheritance for JS, which - next to > > extending the Object prototype - was the biggest complaint about the > > design of that library. Of course the implementation was always so > > bad (e.g. browser sniffing) that it didn't merit much discussion. > > `Object.extend` (i.e. simple copying of properties from one object to > another) has been in Prototype since its inception and was mainly a > plain general purpose helper. More of a hindrance it would seem. :) > > The only way it was used in inheritance abstraction is to copy > properties onto constructor's prototype (so you would pass an object > into a helper rather than assign methods to constructor's prototype > manually). Okay. So it is used to mix-in properties. > > Until recently, there was this idiotic sniff for `Browser.IE` when > working around DontEnum bug in `Object.extend`, but that's because none > of us seemed to know what it was (workaround was only taking care of > "toString" and "valueOf", and in a rather inefficient manner). Hopefully you replaced that with a feature test (and added the other affected properties). But think of all of the Prototype-based sites out there. They will have to upgrade the whole thing with all of the other changes made to that project included and then start QA testing from ground zero. > > Actual inheritance, though, has always been done via Lasse clone/inherit > -like approach. Okay. It's something about the construction of objects that was out of line in that library. > > [...] > > >>> // Is a given value a DOM element? > >>> _.isElement = function(obj) { > >>> return !!(obj && obj.nodeType == 1); > >>> }; > >>> Even worse (trying to differentiate between host and Object objects). > >>> Cool though! > >> Are you sure? I thought this is for filtering out element nodes (from > >> comment, text, etc.). > > > No, I'm not sure. The name and comment seem to indicate a GP > > function. But if so, it seems completely unneeded (all it does is > > check if nodeType == 1). Certainly no good for GP usage. > > Yeah, that's pretty simplistic. > > > > >>> // Is a given value a real Array? > >>> _.isArray = function(obj) { > >>> return Object.prototype.toString.call(obj) == '[object Array]'; > >>> }; > >>> Always an indication of a bad script. And this "Miller > >>> device" (quotes indicate the technique doesn't originate with that > >>> guy) is not 100% reliable (as discussed here repeatedly). > >> It's good enough 99% of the time. Everything else can be considered > >> exception (e.g. cross-window object wrappers in IE). > > > That's as maybe. It's never needed. > > I'm not a big fan of duck typing, but sure, that's another way :) My point is that you can design your app so that it doesn't need to tell an Array object from an Object object. Duck typing would be a fallback for the "Miller Device" that could make an isArray (or isWhatever) a bit closer to 100% reliable, but why bother? > > > > >>> // Is a given value a Function? > >>> _.isFunction = function(obj) { > >>> return Object.prototype.toString.call(obj) == '[object Function]'; > >>> }; > >>> Well, this one is just silly. Could use typeof for Function objects, > >> Nope. Did you forget what typeof reports for regex objects in webkit? > > > Of course not. Second sentence in the documentation for such a > > function (after host object warning) should be "Do not use with RegExp > > objects". It stands to reason that a design that sets out to discern > > between Function and RegExp objects is a design in need of a rewrite. > > But it's not even about discerning. What if regex ends up as an argument > of your function and that function invokes `call` on it after testing it > with `typeof`? regex don't have call (unless you give it to them) so it > will fail. As it should. If the documentation stipulates No RegExp objects are to be passed to this function, then the behavior with a RegExp argument is undefined. It should be expected to fail when passed a RegExp. And, though irrelevant, I disagree that the RegExp in question is not callable. Unless you mean calling its - call - method? > > Too many limitations and exceptions is also annoying. What "too many" > means is of course subjective, and what's annoying to me might be fine > to you. An API should not enable bad design decisions. If you look at the fact that most of the "majors" struggled with awful versions of these is* "overloading" helpers. Wouldn't it have saved a lot of time to determine they are a bad idea from the start? > > I don't see much harm in employing [[Class]] based test, though. At the very least, the limitations should be documented. Advice to avoid the function would make sense too, but I know that wouldn't be cool. > > > > > And none of these "overloading" functions are conducive to good design > > anyway. If you consider a case that is do-able (e.g. string vs. > > function), it boils down to the typeof operator. So why wrap that in > > a function? > > To abstract and provide a common interface. What else could be the reason.. I wasn't looking for an answer, just remarking that such an operation is better left inline. > > > > > > >>> of course, but I imagine this is aimed at developers who wish to > >>> design applications that must differentiate between host object > >>> methods and native functions. Why such designs would ever be > >>> considered is beyond me. > >>> // Is a given variable undefined? > >>> _.isUndefined = function(obj) { > >>> return typeof obj == 'undefined'; > >>> }; > >>> Didn't need that. > >> How so? > > > Same reason you don't need an isFunction. Just use the typeof > > operator and document accordingly. > > >> Don't forget, operators are not first class objects in Javascript ;) > > >> [...] > > >>> // Keep the identity function around for default iterators. > >>> _.identity = function(value) { > >>> return value; > >>> }; > >>> // Break out of the middle of an iteration. > >>> _.breakLoop = function() { > >>> throw "__break__"; > >>> }; > >>> OMG. > >> Yes, that's usually unnecessary. Makes things needlessly slow. > > > Besides that, what sort of design throws in the middle of a loop? And > > who throws strings? > > I suppose they throw to stop iteration (as Prototype does). > Whether they > throw string or something else doesn't seem to make much difference. Seems like quite a difference to me. > > Prototype realized that being able to stop iteration is not worth > performance hit of wrapping it with try-catch. That's good. > > Maybe one day these guys will come to the same conclusion :) The question is whether anyone will care. Waiting on "those guys" to learn browser scripting has been the mantra for years. Look what a mess that has made. > > [...] > > > > >>> /*------------------------ Setup the OOP Wrapper: > >>> --------------------------*/ > >>> // Helper function to continue chaining intermediate results. > >>> var result = function(obj, chain) { > >>> return chain ? _(obj).chain() : obj; > >>> }; > >>> // Add all of the Underscore functions to the wrapper object. > >>> _.each(_.functions(), function(name) { > >>> wrapper.prototype[name] = function() { > >>> Array.prototype.unshift.call(arguments, this._wrapped); > >>> return result(_[name].apply(_, arguments), this._chain); > >>> }; > >>> }); > >>> // Add all mutator Array functions to the wrapper. > >>> _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', > >>> 'unshift'], function(name) { > >>> wrapper.prototype[name] = function() { > >>> Array.prototype[name].apply(this._wrapped, arguments); > >>> return result(this._wrapped, this._chain); > >>> }; > >>> }); > >>> // Add all accessor Array functions to the wrapper. > >>> _.each(['concat', 'join', 'slice'], function(name) { > >>> wrapper.prototype[name] = function() { > >>> return result(Array.prototype[name].apply(this._wrapped, > >>> arguments), this._chain); > >>> }; > >>> }); > >>> // Start chaining a wrapped Underscore object. > >>> wrapper.prototype.chain = function() { > >>> this._chain = true; > >>> return this; > >>> }; > >>> // Extracts the result from a wrapped and chained object. > >>> wrapper.prototype.value = function() { > >>> return this._wrapped; > >>> }; > >>> })(); > >>> Definitely saw this ending coming. ;) All in all, a mishmash of > >>> ideas (most of the bad). I need a rubber stamp that reads "Avoid like > >>> the Plague". > >> It's a clone of Prototype, stuffed into one object, instead of > >> augmenting built-ins. > > > I see MooTools as more of a clone of Prototype. This is just an > > abbreviated mishmash. BTW, are you still working on that thing? > > Rarely. That's just a step away from never. :) > > Last couple of months I've been working on ECMAScript compliance test > suite that can be run a browser. It's actually just a wrapper around > Google's Sputniktests (thanks to Google for doing all the heavy work), > adopted for running in a web page. > > Hopefully, this will eliminate most of the chaos in current > implementations and prevent regresssions in future work. One can only hope. > > Check it out http://thinkweb2.com/projects/prototype/sputniktests-web-runner/ I will when I get a chance. > > How is your dojo work going? > Great, but now I'm too busy working on Dojo applications to work on the project. I'll get back to it eventually. For now, I work around the problems as that is where the money is. ;)
From: Richard Cornford on 10 Nov 2009 06:31 On Nov 9, 9:07 pm, Peter Michaux wrote: > On Nov 9, 2:41 pm, Asen Bozhilov wrote: > <snip> >> The concern of the topic is identifiers name. What is the >> benefit from identifier like: >> _ >> $ > > I think the benefit is they are short. Too short and cryptic, > I think. Yes, short and cryptic (or at least under-descriptive) names don't contribute much to script authoring efforts as the little time they may save in typing in code is almost certainly negated by orders of magnitude of more time squandered during debugging/maintenance. And then there is the hugely increased chance of naming collisions which leaves the authors of, for example, JQurey code wrapping everything they write in structures like:- (function ($){ // actual code using $( ... ) })(JQurey); - in order that "other code" that defines its own - $ - functions/ objects is not be impacted by Query's use of that identifier. If you wanted something to flag a bad idea, finding yourself jumping through hoops as a consequence (and in order to carry on doing it) is probably as good an indicator as any. Still, some mistakes are difficult to back out off, even when recognised. >> I associated underscore with properties whos been "private". >> So i don't make documentation for properties who identifier >> name start with underscore. >> $ symbol in normal live i associated with USA dollar. In Ecma3: > >> | 7.6 Identifiers >> | This standard specifies one departure from the grammar given >> | in the Unicode standard: The dollar sign ($) and the >> | underscore (_) are permitted anywhere in an identifier. The >> | dollar sign is intended for use only in mechanically >> | generated code. > >> So using $ for identifier name from programmers will be means >> contradiction with ECMA3 documentation. > > The use of $ in an indentifier doesn't contradict ECMAScript 3 > because $ was "intended for" not "reserved for". This issue has > been discussed in c.l.js many times. I believe this statement > is gone from the proposed ECMAScript 5 and if so I think it is > good they removed it. The pragmatic recognition that the horse has long since bolted does not imply approval of the actions of whoever let it out, or their consequences. Richard.
From: Tim Down on 10 Nov 2009 09:40 On Nov 9, 10:34 pm, David Mark <dmark.cins...(a)gmail.com> wrote: > if (atype !== 'object') return false; > > Strict comparison is unneeded here. I'm sure you've answered this before, but what is your beef with using strict comparison operators when they're not needed? the only argument I can see against it is the use of one extra character. > And none of these "overloading" functions are conducive to good design > anyway. If you consider a case that is do-able (e.g. string vs. > function), it boils down to the typeof operator. So why wrap that in > a function? The benefit of using isWhatever functions for the doable cases is that you remove the possibility of introducing bugs by mistyping the comparison string ("function", "string", etc.) that exists if using inline typeof comparisons. Tim
From: Thomas 'PointedEars' Lahn on 10 Nov 2009 13:12 Tim Down wrote: > On Nov 9, 10:34 pm, David Mark <dmark.cins...(a)gmail.com> wrote: >> if (atype !== 'object') return false; >> >> Strict comparison is unneeded here. > > I'm sure you've answered this before, but what is your beef with using > strict comparison operators when they're not needed? the only argument > I can see against it is the use of one extra character. The latest test results for the local ECMAScript Support Matrix (checked in yesterday) support that assessment. Transposed: Feature: !== Title: Strict Equals operator JavaScript: 1.3 JScript: 5.1.5010 ECMAScript: 3 JSCore: 525.19 Opera: 5.02 KJS: 3.5.9 Corrections for earlier versions of the implementations are welcome. >> And none of these "overloading" functions are conducive to good design >> anyway. If you consider a case that is do-able (e.g. string vs. >> function), it boils down to the typeof operator. So why wrap that in >> a function? > > The benefit of using isWhatever functions for the doable cases is that > you remove the possibility of introducing bugs by mistyping the > comparison string ("function", "string", etc.) that exists if using > inline typeof comparisons. In a runtime environment with host-defined properties you cannot pass a value if you do not know whether the identifier you are using a) resolves to a property and b) if so, if that property stores a value that is suitable for being passed. (That is why isMethod() primarily uses property names now.) PointedEars -- Use any version of Microsoft Frontpage to create your site. (This won't prevent people from viewing your source, but no one will want to steal it.) -- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)
From: Thomas 'PointedEars' Lahn on 10 Nov 2009 13:18
Thomas 'PointedEars' Lahn wrote: > Feature: !== > Title: Strict Equals operator Typo: Strict _Not_ Equals operator. |