I have a little trouble porting stuff to from prototype 1.4 to 1.5.
Some has to do with ticket #3592, where the results of filters on
enumerables are discussed. As long as this patch is not accepted I
could just patch the behaviour for myself, overloading Enumerables
reject and findAll methods after loading prototype.js.
This would work, because the Enumerable methods were copied to the
Hash object _when_creating_a_new_Hash_.
Now with 1.5 that cannot be done anymore, because the Enumerable
methods are copied to the Hash _prototype_, from where they are
copied by JS when instatiating a new Hash via the new operator.
So effectively to overwriite Enumerable methods I would have to
reextend Hash.prototype with Enumerable after applying my fixes on
Enumerable (the same goes for Array and Range and future Enumerable
descendants).
Now my question is: What is the advantage of the new Hash
implementation? Why did Class.create not suffice? I can see added
complexity but no real gain, since Enumerable is not really in the
prototype chain of Hash, its methods are just copied to the Hashes
prototype.
Please don't think I want to troll around, I am really appreciating
your work.
I have a lot of code depending on Prototype and there is just so much
broken now.
On the other hand I would not want to miss on features and
improvements by staying on 1.4, you see.
Alex
On Feb 8, 6:26 pm, Alexander Presber <aljos...@weisshuhn.de> wrote:
> Now my question is: What is the advantage of the new Hash
> implementation? Why did Class.create not suffice? I can see added
> complexity but no real gain, since Enumerable is not really in the
> prototype chain of Hash, its methods are just copied to the Hashes
> prototype.
The advantage is the reason that prototypes exist in JavaScript in the
first place. Using the previous method (copying methods onto each
instance), if you create 100 you've got to make 100 copies of your
inherited methods. With prototype-based inheritance they all point to
the same copy. It's a big win for memory usage. Read this interview
with Dean Edwards: http://snook.ca/archives/writing/an_interview_wi/
That said, if you need to redefine Enumerable methods I don't think
it's that much of an inconvenience to do:
Enumerable.findAll =
Array.prototype.findAll =
ObjectRange.prototype.findAll =
Hash.prototype.findAll = function() { /* ... */ }
It's certainly not pretty, but you could roll it up into some sort of
function if you're redefining Enumerable methods that often.
More to the point: why override Enumerable methods when you can define
new ones -- "customFindAll" or "_reject" or something like that?
Seems more future-proof and friendlier to other scripts.
I agree that we need to apply this patch and will raise some hell
forthwith. In the meantime, the issue is specific to Hash, so can't
you do...
Object.extend(Hash.prototype, {
reject: function() { /* ... */ },
findAll: function() { /* ... */ },
_add: function() { /* ... */ },
_new: function() { /* ... */ }
});
I think this is the best band-aid until this problem gets permanently
fixed.
On Feb 8, 6:26 pm, Alexander Presber <aljos...@weisshuhn.de> wrote:
Thanks :-)
Here is my (slightly more prototypish) solution for now:
$A([Array, Hash, Range]).each(function(c){Object.extend(
c.prototype, {
reject: function() { /* ... */ },
findAll: function() { /* ... */ }
})});
Cheers, Alex
I see your point. But this is not exactly what happens here.
We do indeed save memory by putting the methods into the Hashes
constructor.
I completely missed that and it is indeed an advantage.
But Dean Ewards is promoting true javascript inheritance, which means
not copying Enumerables methods into our constructor, but
putting Enumerable into our prototype chain. This saves even more
memory (no copying of any methods to extended classes, leave alone
instances) and leaves Enumerable "open", which means we can still
override Enumerables methods and add new ones, even on instantiated
objects.
Now that seems to be on the list of things to do as most people here
probably know. See here
http://encytemedia.com/blog/articles/2006/05/23/prototype-inheritance-
madness and here:
http://sam.conio.net/articles/better-inheritance-for-prototype
But for now it is probably safe to state that the new inheritance
scheme for Enumerable
solves some problems (memory footprint) while creating others
(backwards compatibility, "openness"), at least for some people.
Probably the tradeoff is a positive one for most people, sadly not
including me at this time :-(.
How is the state of affairs in introducing Dean Edwards Base
inheritance to prototype? There are some tickets on inheritance, but
one especially for that?
Cheers, Alex
How is the state of affairs in introducing Dean Edwards Base
inheritance to prototype? There are some tickets on inheritance, but
one especially for that?
Dean has explained the use of Base on his blog
http://dean.edwards.name/weblog/2006/03/base
The code accompanying "Pro JavaScript Techniques" by John Resig has a
slightly commented version of Base.js (Chapter 3)
http://www.apress.com/book/supplementDownload.html?bID=10163&sID=4026
For something entirely different, Alex Arnell has an inheritance
implementation that (purportedly) plays well with Prototype
http://twologic.com/projects/inheritance/
In case anyone was interested...
Michael
--
Michael Schuerig
mailto:mic...@schuerig.de
http://www.schuerig.de/michael/
On Feb 8, 7:59 pm, Alexander Presber <aljos...@weisshuhn.de> wrote:
> > With prototype-based inheritance they all point to
> > the same copy. It's a big win for memory usage. Read this interview
> > with Dean Edwards:http://snook.ca/archives/writing/an_interview_wi/
>
> I see your point. But this is not exactly what happens here.
>
> We do indeed save memory by putting the methods into the Hashes
> constructor.
> I completely missed that and it is indeed an advantage.
>
> But Dean Ewards is promoting true javascript inheritance, which means
> not copying Enumerables methods into our constructor, but
> putting Enumerable into our prototype chain. This saves even more
> memory (no copying of any methods to extended classes, leave alone
> instances) and leaves Enumerable "open", which means we can still
> override Enumerables methods and add new ones, even on instantiated
> objects.
Yes, what you're describing would be ideal, but play around with it
for just a few minutes in FireBug and you'll realize it can't be done.
There's no way to slip an arbitrary object into the prototype chain of
a builtin, so the only alternative is to copy Enumerable over to
Array.prototype via Object.extend.
Now, custom objects like Hash are a different matter. But I think
it's better to be consistent. If redefining Enumerable.reject updated
Hash.prototype.reject and ObjectRange.prototype.reject but not
Array.prototype.reject, then that'd be confusing. Also, the principle
of least surprise dictates that we adhere to Ruby conventions whenever
possible. In Ruby, Enumerable is a mixin, not a class. Better, then,
to use Object.extend (which functions like a mixin) than to have
objects inherit from Enumerable.
> How is the state of affairs in introducing Dean Edwards Base
> inheritance to prototype? There are some tickets on inheritance, but
> one especially for that?
It's a stated goal for 2.0; I'd love to get it into the codebase even
sooner. I think it'd take until 2.0 to rewrite the existing classes
(Ajax.*, for instance) to follow a proper inheritance model, but that
doesn't mean we have to wait until 2.0 to introduce something Base-
like. Ultimately it's up to Sam, though.
Cheers,
Andrew