Mixing In JS Getters and Setters with Class.create

89 views
Skip to first unread message

Antoine Quint

unread,
Jul 2, 2008, 8:51:38 AM7/2/08
to rubyonrail...@googlegroups.com
Hi,

I'm trying to mix native JS getters and setters with Class.create,
with little success so far. Here's what I tried:

=====8<=====

var MyClass = {};

MyClass.__defineGetter__('test', function() {
alert('inside getter');
return 'foo';
});

MyClass.__defineSetter__('test', function(new_value) {
alert('inside setter');
return new_value;
});

MyClass = Class.create(MyClass);

var foo = new MyClass();
foo.test; // should alert 'inside getter'
foo.test = 'bar'; // should alert 'inside setter'

=====>8=====

Evaluating this code with prototype 1.6.0.2 I only get the 'inside
getter' message alerted, but not the setter one, so getters resist
Class.create but not setters. Is there something wrong I'm doing or
are setters just not supported in prototype?

I'll note that I'm working against Safari on iPhone only so I'm not
worried about compatibility issues while using JS getters and setters.

Thanks for your help,

Antoine

darrin

unread,
Jul 2, 2008, 10:28:44 AM7/2/08
to Ruby on Rails: Spinoffs
Interesting, first time I've seen this. The alert is actually coming
out of Class.create call. What about this....

var MyClass = Class.create({
initialize: function() {
this.__defineGetter__('test', function() {
alert('inside getter');
return 'foo';
});

this.__defineSetter__('test', function(new_value) {
alert('inside setter');
return new_value;
});
}
});

Antoine Quint

unread,
Jul 2, 2008, 10:52:53 AM7/2/08
to rubyonrail...@googlegroups.com
Hi Darrin,

On Jul 2, 2008, at 16:28 , darrin wrote:

> Interesting, first time I've seen this. The alert is actually coming
> out of Class.create call. What about this....
>
> var MyClass = Class.create({
> initialize: function() {
> this.__defineGetter__('test', function() {
> alert('inside getter');
> return 'foo';
> });
>
> this.__defineSetter__('test', function(new_value) {
> alert('inside setter');
> return new_value;
> });
> }
> });

That works fine indeed. Do you have any idea why that is while the
previous snippet did not work?

The reason I ask is because I personally dislike the programming style
where properties are defined inline the object passed as the parameter
to Class.create(), and I prefer to have separate "MyClass.aFunction =
function ()" calls. Do you think there is a way to get getters and
setters to work in this style?

Thanks a lot for your help,

Antoine

Ryan Gahl

unread,
Jul 2, 2008, 11:01:31 AM7/2/08
to rubyonrail...@googlegroups.com
It probably has something to do with the fact that you are defining the getter/setter statically on the class itself, where in the second example, you are actually defining them at the instance level, which is what you want.

In your first example, I'll bet if you just do MyClass.test = "blah" it would give you your alert...

You probably just need to a) do your Class.create() first, and b) then apply your getters/setters via the prototype object of the class function:

var MyClass = Class.create();
MyClass.prototype.__defineGetter__("test", someFunction);


...etc...
--
Ryan Gahl
Manager, Senior Software Engineer
Nth Penguin, LLC
http://www.nthpenguin.com
--
WebWidgetry.com / MashupStudio.com
Future Home of the World's First Complete Web Platform
--
Inquire: 1-920-574-2218
Blog: http://www.someElement.com
LinkedIn Profile: http://www.linkedin.com/in/ryangahl

Antoine Quint

unread,
Jul 2, 2008, 11:08:48 AM7/2/08
to rubyonrail...@googlegroups.com
Hi Ryan,

On Jul 2, 2008, at 17:01 , Ryan Gahl wrote:

> It probably has something to do with the fact that you are defining
> the getter/setter statically on the class itself, where in the
> second example, you are actually defining them at the instance
> level, which is what you want.

I don't intend to have them defined on the class itself. I define them
on MyClass indeed, but when I do "MyClass = Class.create(MyClass)", I
think that should have copied class members onto the MyClass
prototype, isn't that right?

I guess the issue there is that these special __defineGetter__ and
__defineSetter__ members are not recognized by Class.create() and thus
aren't copied onto the prototype.

Antoine

Ryan Gahl

unread,
Jul 2, 2008, 11:11:16 AM7/2/08
to rubyonrail...@googlegroups.com
Why would Class.create() copy static class members to the prototype? That doesn't make any sense. That completely rules out the possibility that the developer, you know, wanted them to remain static...

Antoine Quint

unread,
Jul 2, 2008, 11:15:51 AM7/2/08
to rubyonrail...@googlegroups.com
On Jul 2, 2008, at 17:11 , Ryan Gahl wrote:

> Why would Class.create() copy static class members to the prototype?
> That doesn't make any sense. That completely rules out the
> possibility that the developer, you know, wanted them to remain
> static...

As far as I know, that's how Class.create works. See http://prototypejs.org/learn/class-inheritance
and more particularly the Defining class methods section: "There is
no special support for class methods in Prototype 1.6.0. Simply define
them on your existing classes". Then the example shows how class
methods need to be defined _after_ the Class.create() call.

Antoine

Ryan Gahl

unread,
Jul 2, 2008, 11:27:40 AM7/2/08
to rubyonrail...@googlegroups.com
Nowhere on that page does it say that static class methods are copied to the prototype. If, for whatever reason, it actually IS supposed to work that way, it's a major flaw, and should be fixed immediately. But like I said, it wouldn't make any sense if it worked like that, and so it doesn't.

So, with that - just do what darrin suggests (which is the best way to ensure your instance methods are truly instance only methods)... or attach them directly to the prototype object after Class.create() is called.

Antoine Quint

unread,
Jul 2, 2008, 11:43:30 AM7/2/08
to rubyonrail...@googlegroups.com
On Jul 2, 2008, at 17:27 , Ryan Gahl wrote:

> Nowhere on that page does it say that static class methods are
> copied to the prototype.

I think there are only ever static class methods passed in
Class.create(). When you do this:

Class.create({
initialize: function() {
// some code here
}
});

you are passing Class.create an anonymous object with a single static
method defined on it. That object could not be used to create a class
with the "new" construct, it has no constructor to speak of. That's
the whole premise of Class.create as I understand it, you pass it an
anonymous object which really is just a class definition.

The style I use to create classes with Class.create is to actually
name that anonymous object, define what will be instance methods as
static methods on it, pass that object to Class.create() and update
the object with what is returned. So what I wrote above is rewritten
that way and is equivalent as I understand it.

MyClass = {};

MyClass.initialize = function () {
// some code here
};

MyClass = Class.create(MyClass);

> If, for whatever reason, it actually IS supposed to work that way,
> it's a major flaw, and should be fixed immediately. But like I said,
> it wouldn't make any sense if it worked like that, and so it doesn't.

I think it's a pretty elegant design and it's actually the reason I
chose Prototype as a base framework, because I really liked how it
lets one define classes.

> So, with that - just do what darrin suggests (which is the best way
> to ensure your instance methods are truly instance only methods)...
> or attach them directly to the prototype object after Class.create()
> is called.


I think I'll just have a special method called in .initialize that
will map the getters and setters automatically. I was just hoping that
Prototype might already have a way to deal with JS getters and setters
outside of the constructor.

Antoine

kangax

unread,
Jul 2, 2008, 12:36:08 PM7/2/08
to Ruby on Rails: Spinoffs


On Jul 2, 11:43 am, Antoine Quint <anto...@graougraou.com> wrote:
> On Jul 2, 2008, at 17:27 , Ryan Gahl wrote:
>
> > Nowhere on that page does it say that static class methods are
> > copied to the prototype.
>
> I think there are only ever static class methods passed in
> Class.create(). When you do this:
>
> Class.create({
> initialize: function() {
> // some code here
> }
>
> });
>
> you are passing Class.create an anonymous object with a single static
> method defined on it. That object could not be used to create a class

There are no "static" or "instance" methods on js objects really : )
I understand what you mean, but it just sounds confusing.

> with the "new" construct, it has no constructor to speak of. That's
> the whole premise of Class.create as I understand it, you pass it an
> anonymous object which really is just a class definition.
>
> The style I use to create classes with Class.create is to actually
> name that anonymous object, define what will be instance methods as
> static methods on it, pass that object to Class.create() and update
> the object with what is returned. So what I wrote above is rewritten
> that way and is equivalent as I understand it.
>
> MyClass = {};
>
> MyClass.initialize = function () {
> // some code here
>
> };
>
> MyClass = Class.create(MyClass);
>

I've never seen such way of defining "classes". It seems weird to
first create a reference to an empty object literal, then redefine it
to point to a "class" definition. Whatever works for you.

> > If, for whatever reason, it actually IS supposed to work that way,
> > it's a major flaw, and should be fixed immediately. But like I said,
> > it wouldn't make any sense if it worked like that, and so it doesn't.
>
> I think it's a pretty elegant design and it's actually the reason I
> chose Prototype as a base framework, because I really liked how it
> lets one define classes.
>

Prototype doesn't provide any special facility for defining "static"
members (as majority defines it). All it takes is to declare them as
members of "class" function.

var Foo = Class.create({ ... })
Foo.blah = 'my static property';

> > So, with that - just do what darrin suggests (which is the best way
> > to ensure your instance methods are truly instance only methods)...
> > or attach them directly to the prototype object after Class.create()
> > is called.
>
> I think I'll just have a special method called in .initialize that
> will map the getters and setters automatically. I was just hoping that
> Prototype might already have a way to deal with JS getters and setters
> outside of the constructor.
>

You could do that, though "fat" constructors is usually not a good
idea. It would also cripple performance if constructor is called
frequently.

-- kangax

Antoine Quint

unread,
Jul 2, 2008, 1:04:02 PM7/2/08
to rubyonrail...@googlegroups.com
Hi,

On Jul 2, 2008, at 18:36 , kangax wrote:

>> Prototype doesn't provide any special facility for defining "static"
> members (as majority defines it). All it takes is to declare them as
> members of "class" function.
>
> var Foo = Class.create({ ... })
> Foo.blah = 'my static property';

Yeah, that's what I do and it works just fine.

>>> So, with that - just do what darrin suggests (which is the best way
>>> to ensure your instance methods are truly instance only methods)...
>>> or attach them directly to the prototype object after Class.create()
>>> is called.
>>
>> I think I'll just have a special method called in .initialize that
>> will map the getters and setters automatically. I was just hoping
>> that
>> Prototype might already have a way to deal with JS getters and
>> setters
>> outside of the constructor.
>>
>
> You could do that, though "fat" constructors is usually not a good
> idea. It would also cripple performance if constructor is called
> frequently.

I think it might be worth asking for JS getters and setters to be
handled directly by Class.create(). I'll try to add support for them
in Class.create() and submit a patch...

Antoine

Ryan Gahl

unread,
Jul 2, 2008, 1:12:01 PM7/2/08
to rubyonrail...@googlegroups.com
There are no "static" or "instance" methods on js objects really : )
I understand what you mean, but it just sounds confusing.

Of course there are. To say otherwise is confusing.

You could do that, though "fat" constructors is usually not a good
idea. It would also cripple performance if constructor is called
frequently.

Not true at all. "fat" constructors? Let's not make up FUD terms here :)

The truth is, defining methods and properties from within the constructor is the ONLY way to achieve truly instance only members, and the only way to create truly private/public members on the instance (instead of people just adding an underscore character to a public member and calling it private).

For 95% of classes, there will be no noticeable performance issues.

kangax

unread,
Jul 2, 2008, 3:10:21 PM7/2/08
to Ruby on Rails: Spinoffs


On Jul 2, 1:12 pm, "Ryan Gahl" <ryan.g...@gmail.com> wrote:

> Of course there are. To say otherwise is confusing.

I'm not sure I understand what you mean, Ryan.
JavaScript doesn't have a notion of "static" (except for a reserved
keyword that's not even implemented). There are "direct" members and
members shared via object's [[Prototype]]. Since prototype.js
simulates "classes" a reasonable definition of static would be:
properties of a Function object created via Class.create. The way
Antoine put it sounds confusing to me (and I'm sure to other folks as
well)

> You could do that, though "fat" constructors is usually not a good
>
> > idea. It would also cripple performance if constructor is called
> > frequently.
>
> Not true at all. "fat" constructors? Let's not make up FUD terms here :)
>

Doesn't really matter how we call it : )
Having bunch of logic in constructor is not a good design (in my
experience)

> The truth is, defining methods and properties from within the constructor is
> the ONLY way to achieve truly instance only members, and the only way to

"instance only" members could be easily created by assigning functions
to properties of object's prototype. I don't see a need for
constructor.

> create truly private/public members on the instance (instead of people just
> adding an underscore character to a public member and calling it private).
>
> For 95% of classes, there will be no noticeable performance issues.

It's obviously a matter of priorities. For me, performance is usually
one of the key factors. Simulating "private" properties (in a highly
dynamic language) does not compensate for the decreased speed.

-- kangax

Ryan Gahl

unread,
Jul 2, 2008, 3:36:31 PM7/2/08
to rubyonrail...@googlegroups.com
It's obviously a matter of priorities. For me, performance is usually
one of the key factors. Simulating "private" properties (in a highly
dynamic language) does not compensate for the decreased speed.
 
But, there is no decreased speed noticeable, is what I'm saying. So you're sacrificing nothing to gain the benefits of private members, with public accessors. And, it's not a "simulation" -- adding an underscore and calling it private is closer to simulation. What I'm talking about is TRUE public vs. private exposure. There is nothing simulated about it.


Doesn't really matter how we call it : )
Having bunch of logic in constructor is not a good design (in my
experience)

You're experience is wrong here, if it tells you that implementing instance only members, and truly private members, is not good design. It's an extremely valuable pattern, with very clear benefits. Your way is another pattern, with its own benefits. In MY experience (building massive single page high performance RIAs for large clients)... the benefits of projecting the long used classical OO paradigm (which as we all know is really one of the points of Prototype.js) into javascript far outweigh the (completely unnoticeable) performance issues. The assignment of a series of properties and methods within a contructor is NOT the same as the processing that those methods eventually do when they get called. You will never see a difference in performance in a live application. You can run some wildly inaccurate "create a million instances" side by side tests... and still only see a minor difference. Your claims simply have no basis, and it really is borderline FUD.

Even assigning a member via a constructor function's prototype is technically not instance only, because of the simple fact that it sill possible to access the member statically be doing "someClass.prototype.doSomething()". YES, I know this is not a real issue, because not many (smart) people will be calling methods directly against the prototype object... but does illustrate what I mean by TRULY instance-only.

For more information: http://www.someelement.com/2007/03/multiple-inheritance-with-prototypejs.html

About half way down I explain a little more about what I mean by "truly instance-only" vs "prototype-static".

It's most definitely a major departure from how most js devs think. But, again, in MY experience, there are very real long term benefits to this approach, all centered around code longevity and maintainability across the diversely distributed skill levels of team members.... and almost NO downside.

kangax

unread,
Jul 2, 2008, 5:14:12 PM7/2/08
to Ruby on Rails: Spinoffs


On Jul 2, 3:36 pm, "Ryan Gahl" <ryan.g...@gmail.com> wrote:
> > It's obviously a matter of priorities. For me, performance is usually
> > one of the key factors. Simulating "private" properties (in a highly
> > dynamic language) does not compensate for the decreased speed.
>
> But, there is no decreased speed noticeable, is what I'm saying. So you're
> sacrificing nothing to gain the benefits of private members, with public
> accessors. And, it's not a "simulation" -- adding an underscore and calling
> it private is closer to simulation. What I'm talking about is TRUE public
> vs. private exposure. There is nothing simulated about it.
>
> Doesn't really matter how we call it : )

I should have been more specific about performance decrease. Speed of
constructor execution has little to do with it. What matters is that
instances don't share methods via their prototype chain. Instead they
carry them as direct members. This leads to an increased memory
footprint and means that instead of O(1) you get O(N). Clearly there
are benefits : ) I find "true" private members (as you call them) of
little necessity when it comes to encapsulation. JavaScript is a
prototypal language. Members are meant to be shared via prototype
chains. Having common conventions like underscored names is a much
more efficient approach (in my experience).

>
> > Having bunch of logic in constructor is not a good design (in my
> > experience)
>
> You're experience is wrong here, if it tells you that implementing instance
> only members, and truly private members, is not good design. It's an
> extremely valuable pattern, with very clear benefits. Your way is another
> pattern, with its own benefits. In MY experience (building massive single
> page high performance RIAs for large clients)... the benefits of projecting
> the long used classical OO paradigm (which as we all know is really one of
> the points of Prototype.js) into javascript far outweigh the (completely
> unnoticeable) performance issues. The assignment of a series of properties
> and methods within a contructor is NOT the same as the processing that those
> methods eventually do when they get called. You will never see a difference
> in performance in a live application. You can run some wildly inaccurate
> "create a million instances" side by side tests... and still only see a
> minor difference. Your claims simply have no basis, and it really is
> borderline FUD.
>
> Even assigning a member via a constructor function's prototype is
> technically not instance only, because of the simple fact that it sill
> possible to access the member statically be doing
> "someClass.prototype.doSomething()". YES, I know this is not a real issue,
> because not many (smart) people will be calling methods directly against the
> prototype object... but does illustrate what I mean by TRULY instance-only.
>
> For more information:http://www.someelement.com/2007/03/multiple-inheritance-with-prototyp...
>
> About half way down I explain a little more about what I mean by "truly
> instance-only" vs "prototype-static".
>
> It's most definitely a major departure from how most js devs think. But,
> again, in MY experience, there are very real long term benefits to this
> approach, all centered around code longevity and maintainability across the
> diversely distributed skill levels of team members.... and almost NO
> downside.
>

My goal was not to go into discussion of "truly" private members
pattern. I know exactly which benefits come with it and I'm glad it
works for you. JavaScript happens to be designed in such way that
"truly" private members (as we know them) destroy one of its main
concepts. This has little to do with general usefulness of
encapsulation patterns and - yes - it does have real life performance
implications. I would appreciate if my reasonings weren't claimed to
be "FUD" : )

Best,
kangax

Ryan Gahl

unread,
Jul 2, 2008, 5:29:36 PM7/2/08
to rubyonrail...@googlegroups.com
I would appreciate if my reasonings weren't claimed to
be "FUD" : )

I said "borderline FUD"   :)

And ok. It's not FUD. It's just not correct.

But once again I disagree with both statements, where you say private members destroy any features of javascript. In fact, they are implemented by taking advantage of the features of javascript. So you are saying "using the dynamic nature of javascript to implement true levels of member accessibility is destroying X? (where i have no idea what X is)". The other statement being your claims on performance.

The only thing I can see is your memory argument. But that is mitigated by good object design, and good resource management. We build applications that run in a single page and create thousands of widget instances. We have a component model that employs a "disposable" interface, where when an instance is no longer needed, dispose() is called on it and its memory allocations are cleaned up (including auto unhooking dom events).

If you create an application that creates so many object instances, where you're using up too much memory and you notice a slow down... then you've got other problems, and no features of javascript are going to save your design.

You're making just plainly false assumptions about a pattern you've clearly never tested. It's different than what you've always done... and therefore somehow bad.

Look, this got a bit sidetracked from the OP... but trust me, the pattern is sound and works in very large scale applications.

Ryan Gahl

unread,
Jul 2, 2008, 5:48:25 PM7/2/08
to rubyonrail...@googlegroups.com
One more little illustration:

var blah = Class.create({
someArray: [],
initialize: function() {}
});

var foo1 = new blah();
var foo2 = new blah();
foo1.someArray.push("blahblah");
alert(foo2.someArray.length); //alerts 1, most people new to js will expect 0

How many times has this issue been posted about here? People write something like this, and expect the array to be unique for both instances, when in fact it's shared (also known as static)... when in fact they really wanted:


var blah = Class.create({
initialize: function() {
this.someArray = [];
}
});

Dan Dorman

unread,
Jul 2, 2008, 6:00:55 PM7/2/08
to rubyonrail...@googlegroups.com
It's gotten a bit testy, but I just wanted to say that I, for one,
have appreciated the discussion thus far ;-)

:Dan

kangax

unread,
Jul 2, 2008, 6:36:50 PM7/2/08
to Ruby on Rails: Spinoffs
I'm not sure what this has to do with anything.
If a person doesn't know what Class.create does with an object (passed
to it), it's their problem ; )
Bending language (and clogging performance) to meet inept programmers
expectations doesn't seem like a wise thing to do.
Adapting a "private members" pattern, on the other hand, is a decision
every person/team has to decide for itself (as there are clear pros/
cons in each situation).

-- kangax

Ryan Gahl

unread,
Jul 2, 2008, 7:17:19 PM7/2/08
to rubyonrail...@googlegroups.com
Seriously, stop with the performance stuff - it's not an issue. You keep bringing it up and I'm here to tell you it's just plain wrong. And my example is a perfect example of the benefit of the assignment of instance members within the constructor as rule. In fact, in this example, it's the ONLY way to make someArray be an instance member across instances (vs. shared across instances, again, also know as static).


Bending language (and clogging performance) to meet inept programmers
expectations doesn't seem like a wise thing to do.

You're clearly not in charge of a team of developers doing long term large scale application development, with a statement like that. You MUST account for programmer skill level disparity. Not doing so IS unwise. This is one of the most critical issues for an architect and project manager... being able to plug in new team members and ensure, to whatever extent is possible, that the basic skillsets needed are as standard as possible and that the code output is consistent. You just will not find a homogeneous team of rockstars that can navigate easily through all the intricacies of the target platform/language and instantly grok everyone else's "uber" coding styles.
And once again, the "clogging performance" statement is erroneous.

All the above said, that's not even the point of my argument (but it's important and is quite contrary to your quote above).

All I'm saying, is that you're wrong about the pattern. I'm not here to convince you to use it, but you are just wrong. It lends itself to extreme scalability, and does not, I repeat, does not adversely affect performance. That's a lie that someone told you, that you never tested, and I just want to stop the propagation of this falsity... lest someone else believe it.

Ryan Gahl

unread,
Jul 2, 2008, 7:32:01 PM7/2/08
to rubyonrail...@googlegroups.com
Just re-read my last post - kangax, sorry for getting all "DUDE!!" on you... I'll try to keep my tone down if we continue the exchange :)

Ryan Gahl

unread,
Jul 2, 2008, 7:40:32 PM7/2/08
to rubyonrail...@googlegroups.com
It's gotten a bit testy, but I just wanted to say that I, for one,
have appreciated the discussion thus far ;-)

Sorry about the feistiness, but glad someone is finding it valuable.

kangax

unread,
Jul 3, 2008, 1:48:56 AM7/3/08
to Ruby on Rails: Spinoffs
Ryan, no need to get offensive about patterns that work for you (and
your team).
I am certainly not throwing pointless arguments about some
hypothetical performance issues. Everything I said comes from
experience in applications I have worked on. It also comes from people
who worked on JS applications of a much larger scale than I have ever
had (and who I learned a great deal of JavaScript from). I have no
intentions of spreading heresy around this place. Your attitude is
surprising at best. Constantly repeating how I'm "plain wrong" and
making up assumptions about my reasonings, my experience and skills is
not something I would expect of you.
I gave a simple explanation of what "static" is referred to in
JavaScript (or rather prototype.js). I also pointed out caveats of
"private members" pattern.
The truth is that there are no silver bullets (that you seem so
desperately convince me to follow).
There are also no "wrong" or "right". There are patterns that work in
one environment and don't work in others.

Regards.

Ryan Gahl

unread,
Jul 3, 2008, 2:09:03 AM7/3/08
to rubyonrail...@googlegroups.com
Constantly repeating how I'm "plain wrong" and
making up assumptions about my reasonings, my experience and skills is
not something I would expect of you.

You are saying things about a pattern that are wrong, and there's no other kind of wrong other than plain :). The only thing I said that was an assumption about your experience was related to the comment you made about "inept developers" - I felt it showed a level of inexperience working on large development teams. I never said anything, however, about your skills. I respect your skills. Especially your skills with a bowstaff and with numchucks :) <napolean dynamite reference>


The truth is that there are no silver bullets (that you seem so
desperately convince me to follow).
There are also no "wrong" or "right". There are patterns that work in
one environment and don't work in others.

First of all, I'm not trying to convince you or anyone else to use one pattern over another. This all started when you made false claims about "fat" constructors and calling it bad design to assign instance properties from within the constructor, saying it "clogs performance".... all untrue statements. That's all I was doing - pointing out that you are incorrect about the pattern. I never said the pattern was more correct vs another pattern. I was simply explaining the benefits, why we use it, and debunking the myths around it, that you seemed to be defending with really no basis.

Ryan, no need to get offensive

I am sorry if my rebuttals got a bit "point blank". I don't think I really said anything too offensive, but if I did I truly do apologize. Hope there's no hard feelings. After all, there's nothing like a heated debate once in a while to fill in the gaps of a busy day :)




RobG

unread,
Jul 3, 2008, 6:49:32 AM7/3/08
to Ruby on Rails: Spinoffs


On Jul 3, 4:09 pm, "Ryan Gahl" <ryan.g...@gmail.com> wrote:
> > Constantly repeating how I'm "plain wrong" and
> > making up assumptions about my reasonings, my experience and skills is
> > not something I would expect of you.
>
> You are saying things about a pattern that are wrong, and there's no other
> kind of wrong other than plain :).

When claiming something as categorically wrong, there only needs to be
one exception to disprove the claim.

Kangax's point might be moot for simple constructors, but that doesn't
make it "plain wrong". Suppose you have a constructor with 100
methods and you want 100 instances, is it better to define each and
every method on each and every instance, or put them on the
constuctor's prototype? More simply, would you consider it OK to
create 10,000 function objects when 100 will do the job?

If you are unequivocally right, then Prototype.js should stick with
the strategy employed for IE of adding methods to every DOM element it
encounters as there would be no point in extending HTMLElement
instead.

Much of the argument in this thread comes from the fact that
javascript doesn't have classes, or instance variables, or static
members: but there are various ways of emulating them. What you are
really arguing about are implementation preferences.

Concepts of good, bad, right and wrong are purely subjective. What is
lost in the bluster is that javascript is flexible enough to emulate
just about any OO paradigm you want.


--
Rob

Ryan Gahl

unread,
Jul 3, 2008, 10:34:45 AM7/3/08
to rubyonrail...@googlegroups.com
Kangax's point might be moot for simple constructors, but that doesn't
make it "plain wrong".  Suppose you have a constructor with 100
methods and you want 100 instances, is it better to define each and
every method on each and every instance, or put them on the
constuctor's prototype?  More simply, would you consider it OK to
create 10,000 function objects when 100 will do the job?

That's one of those irrelevant, contrived examples of something you'll never see in a full blown real life application. Even then, you just will not see a significant slowdown. Yes, if you, for some reason other than running an ill conceived test, create 10,000 functions at once, you're not making optimal use of memory. Your example assumes 100 instances of the same class (that for some reason has 100 functions??) are ever going to exist, which just will not happen unless you are talking about one of the worst architects on the planet, and once again no use of shared memory tactics will save that project from failure. Please keep in mind I'm not talking about things like "HtmlElement". I'm talking about application classes.


If you are unequivocally right, then Prototype.js should stick with
the strategy employed for IE of adding methods to every DOM element it
encounters as there would be no point in extending HTMLElement
instead.

You guys are confusing what I'm saying. Kangax said encapsulating private/public, instance only members within the constructor is bad design and HE is the one that said this without considering that what he was saying was not categorically correct. I simply jumped in to defend the pattern as a sound and scalable approach to large scale application development, citing the merits of using it. (NOTE: once again, I am not saying that NOT using it is wrong or that your code is not good, simply defending the usage of it as not "bad design")

I never once said Prototype, or you, or kangax, or the OP, should USE it compared to anything else.

Much of the argument in this thread comes from the fact that
javascript doesn't have classes, or instance variables, or static
members: but there are various ways of emulating them.  What you are
really arguing about are implementation preferences.

Javascript does not have classes, true. Javascript does have instance variables, and does have static members (where in the world are you getting this stuff). You're kind of saying "javascript is not object oriented", which it is. Does javascript have instances? Yes, otherwise, what is this: "var blah = new Foo();"? Are the properties and methods that are unique to each instance called instance members? Yes. And what about those members that are shared across instances? What's another word for shared, in object oriented vernacular? Static. And what we're arguing about is the fact that kangax said that a perfectly good design pattern is bad. I said "no, that's wrong and here's why"

If sound OO practice is bad design, than what do you make of the new features centered around these same concepts, that will be in Javascript 2?

Concepts of good, bad, right and wrong are purely subjective

That statement is wrong :) (sorry, had to do it)



kangax

unread,
Jul 3, 2008, 5:42:49 PM7/3/08
to Ruby on Rails: Spinoffs


On Jul 3, 10:34 am, "Ryan Gahl" <ryan.g...@gmail.com> wrote:

> Javascript does not have classes, true. Javascript does have instance
> variables, and does have static members (where in the world are you getting
> this stuff). You're kind of saying "javascript is not object oriented",
> which it is. Does javascript have instances? Yes, otherwise, what is this:
> "var blah = new Foo();"? Are the properties and methods that are unique to
> each instance called instance members? Yes. And what about those members
> that are shared across instances? What's another word for shared, in object
> oriented vernacular? Static. And what we're arguing about is the fact that

Your definition of "static" is what confused me. Why are you calling
shared instance members (where member is property/method) "static"?
Wiki, btw, clearly states that "... a static method cannot refer to a
specific instance of the class (i.e. it cannot refer to this, self,
Me, etc.)..." http://en.wikipedia.org/wiki/Method_(computer_science)#Static_methods
That's pretty much what I wrote earlier about "static" members as
understood by majority - it's a member of constructor, not
constructor's prototype (as you refer to).

// constructor
function Person(name) {
this.name = name;
Person.count++;
};

// static property (defined directly on a constructor)
Person.count = 0;

// shared instance method
Person.prototype.say = function(message) {
return this.name + ' says: ' + message;
}

Same goes for prototype.js

var Person = Class.create({
// constructor
initialize: function(name) {
this.name = name;
Person.count++;
},
// shared instance method
say: function(message) {
return this.name + ' says: ' + message;
}
});

// static property
Person.count = 0;

-- kangax

Ryan Gahl

unread,
Jul 3, 2008, 10:28:19 PM7/3/08
to rubyonrail...@googlegroups.com
Why are you calling
shared instance members (where member is property/method) "static"?

Sorry, that's not what I meant to say. If you read my blog post (http://www.someelement.com/2007/03/multiple-inheritance-with-prototypejs.html) - I explain what I mean by "prototype-static".

Ok, let's look at your example:


// constructor
function Person(name) {
 this.name = name;
 Person.count++;
};

// static property (defined directly on a constructor)
Person.count = 0;

// shared instance method
Person.prototype.say = function(message) {
 return this.name + ' says: ' + message;
}

(btw, you forgot a semicolon there  - and yes I'm pedantic when it comes to missing semicolons :))

So... what I mean by "prototype static" is the fact that after that last line it is now possible to call "Person.prototype.say("blah")" statically (i.e. without having an instance) -- and of course get an error. What I mean by "instance only" members, is any member that is ONLY visible from instances, period. And of course true private variables and methods is another thing I was talking about.

meh... nevermind :)


Jerod Venema

unread,
Jul 3, 2008, 10:58:45 PM7/3/08
to rubyonrail...@googlegroups.com
On Thu, Jul 3, 2008 at 10:28 PM, Ryan Gahl <ryan...@gmail.com> wrote:
Why are you calling
shared instance members (where member is property/method) "static"?

Sorry, that's not what I meant to say. If you read my blog post (http://www.someelement.com/2007/03/multiple-inheritance-with-prototypejs.html) - I explain what I mean by "prototype-static".

Ok, let's look at your example:

// constructor
function Person(name) {
 this.name = name;
 Person.count++;
};

// static property (defined directly on a constructor)
Person.count = 0;

// shared instance method
Person.prototype.say = function(message) {
 return this.name + ' says: ' + message;
}

(btw, you forgot a semicolon there  - and yes I'm pedantic when it comes to missing semicolons :))

<sigh> If you only knew HOW pedantic... :-D

So... what I mean by "prototype static" is the fact that after that last line it is now possible to call "Person.prototype.say("blah")" statically (i.e. without having an instance) -- and of course get an error. What I mean by "instance only" members, is any member that is ONLY visible from instances, period. And of course true private variables and methods is another thing I was talking about.

meh... nevermind :)







--
Jerod Venema

Senior Software Engineer
Nth Penguin, LLC
http://www.nthpenguin.com
(919) 368-5105
---
Reply all
Reply to author
Forward
0 new messages