From: David Mark on
On Nov 9, 5:37 pm, "Michael Haufe (\"TNO\")"
<t...(a)thenewobjective.com> wrote:
> On Nov 9, 2:41 pm, Asen Bozhilov <asen.bozhi...(a)gmail.com> wrote:
>
> > The concern of the topic is identifiers name. What is the benefit from
> > identifier like:
> > _
> > $
>
> It all stemmed from the desire to keep 3rd party code out of the
> global space. As a result, many  major libraries have their own
> "namespace" where they keep their code.

There's really no such thing as a "major" library. I know what you
mean though. Basically, "major" is synonymous with incompetent. How
many of these "majors" can even read an attribute straight? Odd trend
when you consider most hang their hats on CSS selector queries.

> In the case of jQuery, and its
> fad with having the most terse syntax as possible, their "namespace"
> became the "$" symbol. The assumption was that no other library or
> code would have a global variable with that name, while at the same
> time being as short as possible.

And what a monumentally stupid assumption as Prototype came out before
jQuery.

> Since jQuery became popular (due to
> good and bad marketing), many wannabe libraries think a small global
> "namespace" like that is a good idea, so monkey see monkey do.

I can't understand why so many of them wanna produce lousy, legless
scripts. It's as if incompetence and relevance are seen as linked. A
lot of the copied "majors" are on fumes at this point (and soon to be
rusting in the berm). Copying them is a sure path to nowhere.
From: Thomas 'PointedEars' Lahn on
Peter Michaux wrote:

> On Nov 9, 2:41 pm, Asen Bozhilov <asen.bozhi...(a)gmail.com> wrote:
>> | 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 is the same in green.

> This issue has been discussed in c.l.js many times.

But the arguments did not get through to you anyway?

> I believe this statement is gone from the proposed ECMAScript 5 and if so
> I think it is good they removed it.

Well, I for one do not want to see code like the following spreading around:

<?php
$bar = 'baz';
$foo = 'bar';
echo <<<JS
\$foo.\$ = '{$$foo}';
JS;
?>

Do you?


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
From: kangax on
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>
>>

[...]

>
> // Export the Underscore object for CommonJS.
> if (typeof exports !== 'undefined') _ = exports;
>
>
> Waste of time.

Why?

[...]

>
>
> _.each = function(obj, iterator, context) {
> var index = 0;
> try {
> if (obj.forEach) {
> obj.forEach(iterator, context);
> } else if (obj.length) {
> for (var i=0, l = obj.length; i<l; i++) iterator.call(context,
> obj[i], i, obj);
> } else {
> for (var key in obj) if (Object.prototype.hasOwnProperty.call
> (obj, key)) {
> iterator.call(context, obj[key], key, obj);
> }
> }
> } catch(e) {
> if (e != '__break__') throw e;
> }
> return obj;
> };
>
>
> Well, not like _that_ anyway. :(

Pretty bad, indeed.

>
>
> /* ----------------------- Function Functions:
> -----------------------------*/
>
> // Create a function bound to a given object (assigning 'this', and
> arguments,
> // optionally). Binding with arguments is also known as 'curry'.
> _.bind = function(func, context) {
> context = context || root;
> var args = _.toArray(arguments).slice(2);
> return function() {
> var a = args.concat(_.toArray(arguments));
> return func.apply(context, a);
> };
> };
>
> // Bind all of an object's methods to that object. Useful for
> ensuring that
> // all callbacks defined on an object belong to it.
> _.bindAll = function() {
> var args = _.toArray(arguments);
> var context = args.pop();
> _.each(args, function(methodName) {
> context[methodName] = _.bind(context[methodName], context);
> });
> };
>
>
> Bind by method name with an optional context. Deja vu.

Clearly, not the most efficient implementation of bind.

>
>
> // Extend a given object with all of the properties in a source
> object.
> _.extend = function(destination, source) {
> for (var property in source) destination[property] = source
> [property];
> return destination;
> };

Where's DontEnum bug workaround?

>
> // 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.

>
>
> // Perform a deep comparison to check if two objects are equal.
> _.isEqual = function(a, b) {
> // Check object identity.
> if (a === b) return true;
>
> Waste of time.
>
> // Different types?
> var atype = typeof(a), btype = typeof(b);
> if (atype != btype) return false;
> // Basic equality test (watch out for coercions).
> if (a == b) return true;
> // One of them implements an isEqual()?
> if (a.isEqual) return a.isEqual(b);
> // If a is not an object by this point, we can't handle it.
> if (atype !== 'object') return false;

Fails when comparing NaN's, from what I can see.

>
>
> Strict comparison is unneeded here.
>
>
> // Nothing else worked, deep compare the contents.
>
>
> Of course, typeof null == 'object'
>
>
> var aKeys = _.keys(a), bKeys = _.keys(b);
>
>
> So no wonder there is a try-catch in _each.
>
> // Different object sizes?
> if (aKeys.length != bKeys.length) return false;
> // Recursive comparison of contents.
> for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
>
> That's not going to work at all for null (or very well for Object
> objects as the loop is unfiltered).
>
> return true;
> };
>
> // Is a given array or object empty?
> _.isEmpty = function(obj) {
> return (_.isArray(obj) ? obj : _.values(obj)).length == 0;
> };
>
>
> This is a bad design (differentiating between Object and Array
> objects). Perhaps the competent alternative was not "cool"
> enough. :)
>
>
> // 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.).

>
>
> // 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).

>
>
> // 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, 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?

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.

[...]

>
> _.template = function(str, data) {
> var fn = new Function('obj',
> 'var p=[],print=function(){p.push.apply(p,arguments);};' +
> 'with(obj){p.push(\'' +
> str
> .replace(/[\r\t\n]/g, " ")
> .split("<%").join("\t")
> .replace(/((^|%>)[^\t]*)'/g, "$1\r")
> .replace(/\t=(.*?)%>/g, "',$1,'")
> .split("\t").join("');")
> .split("%>").join("p.push('")
> .split("\r").join("\\'")
> + "');}return p.join('');");
> return data ? fn(data) : fn;
> };
>
> /*------------------------------- Aliases
> ----------------------------------*/
>
> _.forEach = _.each;
> _.foldl = _.inject = _.reduce;
> _.foldr = _.reduceRight;
> _.filter = _.select;
> _.every = _.all;
> _.some = _.any;
> _.methods = _.functions;
>
>
> Why?

Those on the left look like JS1.5 extensions / ES5 additions.

>
>
> /*------------------------ 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.

--
kangax
From: David Mark on
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>
>
> [...]
>
>
>
> >   // Export the Underscore object for CommonJS.
> >   if (typeof exports !== 'undefined') _ = exports;
>
> > Waste of time.
>
> Why?

Why export something that nobody wants or needs?

>
> [...]
>
>
>
>
>
> >   _.each = function(obj, iterator, context) {
> >     var index = 0;
> >     try {
> >       if (obj.forEach) {
> >         obj.forEach(iterator, context);
> >       } else if (obj.length) {
> >         for (var i=0, l = obj.length; i<l; i++) iterator.call(context,
> > obj[i], i, obj);
> >       } else {
> >         for (var key in obj) if (Object.prototype.hasOwnProperty.call
> > (obj, key)) {
> >           iterator.call(context, obj[key], key, obj);
> >         }
> >       }
> >     } catch(e) {
> >       if (e != '__break__') throw e;
> >     }
> >     return obj;
> >   };
>
> > Well, not like _that_ anyway.  :(
>
> Pretty bad, indeed.
>
>
>
>
>
> >   /* ----------------------- Function Functions:
> > -----------------------------*/
>
> >   // Create a function bound to a given object (assigning 'this', and
> > arguments,
> >   // optionally). Binding with arguments is also known as 'curry'.
> >   _.bind = function(func, context) {
> >     context = context || root;
> >     var args = _.toArray(arguments).slice(2);
> >     return function() {
> >       var a = args.concat(_.toArray(arguments));
> >       return func.apply(context, a);
> >     };
> >   };
>
> >   // Bind all of an object's methods to that object. Useful for
> > ensuring that
> >   // all callbacks defined on an object belong to it.
> >   _.bindAll = function() {
> >     var args = _.toArray(arguments);
> >     var context = args.pop();
> >     _.each(args, function(methodName) {
> >       context[methodName] = _.bind(context[methodName], context);
> >     });
> >   };
>
> > Bind by method name with an optional context.  Deja vu.
>
> Clearly, not the most efficient implementation of bind.
>
>
>
> >   // Extend a given object with all of the properties in a source
> > object.
> >   _.extend = function(destination, source) {
> >     for (var property in source) destination[property] = source
> > [property];
> >     return destination;
> >   };
>
> Where's DontEnum bug workaround?
>
>
>
> >   // 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.

>
>
>
>
>
> >   // Perform a deep comparison to check if two objects are equal.
> >   _.isEqual = function(a, b) {
> >     // Check object identity.
> >     if (a === b) return true;
>
> > Waste of time.
>
> >     // Different types?
> >     var atype = typeof(a), btype = typeof(b);
> >     if (atype != btype) return false;
> >     // Basic equality test (watch out for coercions).
> >     if (a == b) return true;
> >     // One of them implements an isEqual()?
> >     if (a.isEqual) return a.isEqual(b);
> >     // If a is not an object by this point, we can't handle it.
> >     if (atype !== 'object') return false;
>
> Fails when comparing NaN's, from what I can see.
>
>
>
>
>
> > Strict comparison is unneeded here.
>
> >     // Nothing else worked, deep compare the contents.
>
> > Of course, typeof null == 'object'
>
> >     var aKeys = _.keys(a), bKeys = _.keys(b);
>
> > So no wonder there is a try-catch in _each.
>
> >     // Different object sizes?
> >     if (aKeys.length != bKeys.length) return false;
> >     // Recursive comparison of contents.
> >     for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
>
> > That's not going to work at all for null (or very well for Object
> > objects as the loop is unfiltered).
>
> >     return true;
> >   };
>
> >   // Is a given array or object empty?
> >   _.isEmpty = function(obj) {
> >     return (_.isArray(obj) ? obj : _.values(obj)).length == 0;
> >   };
>
> > This is a bad design (differentiating between Object and Array
> > objects).  Perhaps the competent alternative was not "cool"
> > enough.  :)
>
> >   // 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.

>
>
>
> >   // 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.

>
>
>
> >   // 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.

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?

>
> > 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?

>
> [...]
>
>
>
>
>
> >   _.template = function(str, data) {
> >     var fn = new Function('obj',
> >       'var p=[],print=function(){p.push.apply(p,arguments);};' +
> >       'with(obj){p.push(\'' +
> >       str
> >         .replace(/[\r\t\n]/g, " ")
> >         .split("<%").join("\t")
> >         .replace(/((^|%>)[^\t]*)'/g, "$1\r")
> >         .replace(/\t=(.*?)%>/g, "',$1,'")
> >         .split("\t").join("');")
> >         .split("%>").join("p.push('")
> >         .split("\r").join("\\'")
> >     + "');}return p.join('');");
> >     return data ? fn(data) : fn;
> >   };
>
> >   /*------------------------------- Aliases
> > ----------------------------------*/
>
> >   _.forEach  = _.each;
> >   _.foldl    = _.inject       = _.reduce;
> >   _.foldr    = _.reduceRight;
> >   _.filter   = _.select;
> >   _.every    = _.all;
> >   _.some     = _.any;
> >   _.methods  = _.functions;
>
> > Why?
>
> Those on the left look like JS1.5 extensions / ES5 additions.

Nevertheless. It's their "namespace", so why the aliases?

>
>
>
>
>
> >   /*------------------------ 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?
From: kangax on
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.

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).

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).

Actual inheritance, though, has always been done via Lasse clone/inherit
-like approach.

[...]

>>> // 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 :)

>
>>
>>
>>> // 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.

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.

I don't see much harm in employing [[Class]] based test, though.

>
> 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.

>
>>> 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.

Prototype realized that being able to stop iteration is not worth
performance hit of wrapping it with try-catch.

Maybe one day these guys will come to the same conclusion :)

[...]

>>> /*------------------------ 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.

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.

Check it out �
http://thinkweb2.com/projects/prototype/sputniktests-web-runner/

How is your dojo work going?

--
kangax