From: Ryan Chan on
Have read Douglas Crockfore's JavaScript The Good Parts, it recommend
Augmenting Types, e.g.

Function.prototype.method = function(name, func) {
this.prototype[name] = func;
return this;
};

String.method('trim', function() {
return this.replace(/^\s+|\s+$/g, '');
});


Is this a good thing in your opinion?



From: Thomas 'PointedEars' Lahn on
Ryan Chan wrote:

> Have read Douglas Crockfore's JavaScript The Good Parts, it recommend
> Augmenting Types, e.g.
>
> Function.prototype.method = function(name, func) {
> this.prototype[name] = func;
> return this;
> };
>
> String.method('trim', function() {
> return this.replace(/^\s+|\s+$/g, '');
> });
>
>
> Is this a good thing in your opinion?

No, because the call to String.method() would unconditionally overwrite the
property value in case there was already such a method. There needs to be
one in conforming implementations of ECMAScript Edition 5, so if you use
this exact pattern, you would in effect be replacing the faster built-in
method by a slower user-defined one. It is understandable that the book
does not consider this possibility as Edition 5 was published not before
2009-12. However, that does not excuse the lack of feature test before the
assignment or the lack of a property registry to work around unwanted
enumeration.

As to the question you wanted to ask: Such syntactic sugar can be a good
thing if done properly, and there is little wrong with it in this example.
However, if you augment built-in prototype objects you need to be aware
that all objects that have them in their prototype chain inherit those
properties, and that at least new prototype properties are enumerable (see
for-in iteration). Especially, if you augment the Object prototype object
the new properties will show up with for-in iteration over Array instances,
as their prototype chain is

[object Array] --> Array.prototype --> Object.prototype


PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300dec7(a)news.demon.co.uk>
From: Garrett Smith on
Ryan Chan wrote:
> Have read Douglas Crockfore's JavaScript The Good Parts, it recommend
> Augmenting Types, e.g.
>
> Function.prototype.method = function(name, func) {
> this.prototype[name] = func;
> return this;
> };
>

This is not a good thing.

The `method` method is not related to all Functions; only constructors.

It takes more time to comprehend that method than:-

MyConstructor.prototype.foo = fooFunc;

That method is unnecessary, not well named, adds overhead, adds clutter.

I criticized this part in another thread:
http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/3a08fb741525ab6d/cd561210abc96faa#cd561210abc96faa

> String.method('trim', function() {
> return this.replace(/^\s+|\s+$/g, '');
> });
>

No, it is not a good idea to replace a built-in method with a
hand-rolled version; not without good reason. In fact, without good
reason, that has some negative consequences.

String.prototype.trim is an ES5 standard method. It is implemented in
Tracemonkey (in Firefox).

A good reason for doing that would be, say, if an implementation did not
yet support the new method, or if it was shown to be buggy, but only
then after performing a /feature test/. The FAQ contains an example of
just that.

When Douglas wrote that, he probably did not consider the possibility
that String.prototype.trim would be added to the language.

The consequence of adding String.prototype.trim is that it replaces the
built-in String.prototype.trim with a user-defined version. That
user-defined version will not perform as fast as native code that it
replaced and will throw errors when used in a generic context.

| The following steps are taken:
| 1. Call CheckObjectCoercible passing the this value as its argument.
| 2. Let S be the result of calling ToString, giving it the this value
| as its argument.
| 3. Let T be a String value that is a copy of S with both leading and
| trailing white space removed. The definition of white space is the
| union of WhiteSpace and LineTerminator.
| 4. Return T.
|
| NOTE The trim function is intentionally generic; it does not require
| that its this value be a String object. Therefore, it can be
| transferred to other kinds of objects for use as a method.

The following are specified to work in ES5:

var trimFn = String.prototype.trim;
trimFn.call( window.getSelection() )
trimFn.call( new Error("You broke it.") );
trimFn.call( window.location );
trimFn.call( document.links[0] );

var range = document.createRange();
range.selectNode(document.body);

trimFn.call(range);

In Firefox, they correctly do convert the thisArt to string, as
specified by the standard.

However, when Douglas' method replaces that, it results in a TypeError.

By creating your own namespace, collisions like that can be avoided.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Thomas 'PointedEars' Lahn on
Garrett Smith wrote:

> Ryan Chan wrote:
>> Have read Douglas Crockfore's JavaScript The Good Parts, it recommend
>> Augmenting Types, e.g.
>>
>> Function.prototype.method = function(name, func) {
>> this.prototype[name] = func;
>> return this;
>> };
>>
>
> This is not a good thing.
>
> The `method` method is not related to all Functions; only constructors.

Non sequitur. All Function instances may be used as constructor.

> It takes more time to comprehend that method than:-
>
> MyConstructor.prototype.foo = fooFunc;

Only that this is not equivalent (note the `return'), and if feature-tests
were added as they should be, there would probably be the clutter that you
are talking of below, in the main code.

> That method is unnecessary,

No.

> not well named,

True, it would only qualify as `method' if it checked for method references
for the second argument, and the property name misses a verb (e.g.
setMethod).

> adds overhead,

Any abstraction does. That is not a good reason for not doing it.

> adds clutter.

Define: clutter.

> By creating your own namespace, collisions like that can be avoided.

Whereas `namespace' should be understood as syntactic sugar created by
aggregation, not (yet) as a language feature. One should therefore be
aware that the less probability of name collision that this "namespacing"
provides comes with a performance penalty.


PointedEars
--
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
-- Richard Cornford, cljs, <cife6q$253$1$8300dec7(a)news.demon.co.uk> (2004)
From: Jorge on
On Jan 3, 6:40 am, Ryan Chan <ryanchan...(a)gmail.com> wrote:
> Have read Douglas Crockfore's JavaScript The Good Parts, it recommend
> Augmenting Types, e.g.
>
> Function.prototype.method = function(name, func) {
>     this.prototype[name] = func;
>     return this;
>
> };
>
> String.method('trim', function() {
>     return this.replace(/^\s+|\s+$/g, '');
>
> });
>
> Is this a good thing in your opinion?

The -handy- ability to -miraculously- extend types on the fly -at
runtime- is another of these awesome JS's features that Brendan Eich
put there just for you not to use it. LOL.
--
Jorge.