[Prototype-core] Re: Class.create() and method binding
Dan, check out my blog: http://www.someelement.com - I have only 2 relevant posts, but in both of them I discuss some things that you may find interesting about implementing a classical model in javascript, without sacrificing the power of being able to "do what you want when you want" that javascript gives. Namely, using a true private/public method model... You're right though, experienced js programmers expect to have to track and correct scope issues manually, and IMHO it's not that hard... and if this starts being handled automatically you lose flexibility, as mentioned, for edge cases. On 5/11/07, Dan Webb <[EMAIL PROTECTED]> wrote: > > > > > I wasn't being very clear -- sorry. Those first two examples > > > illustrate what would happen if we implemented *both* the stuff in the > > > events branch as it is now *and* Dan's proposal to bind class methods > > > automatically. > > > > Right! It is exactly where the magic bites. > > Heh, maybe your right. I think, as a JS programmer, that having to > bind functions manually is what you expect to do but as a beginner it > isn't but I suppose there's no point in confusing matters for > experienced JS programmers. In the example here (where this is > normally the element but if you pass in the a Class instance its bound > to the object) I quite like how it works actually but each to their > own. I still think it would be nicer if Class.create() actually > created something that acted like a class from a class based language > rather than just being a normal contructor. > > On that point about base: base.js doesn't bind methods but it does > wrap every method to allow access to its super classes version of the > method which is going to introduce even more of a performance overhead > but hasn't been a problem in my experience. > > > > -- Ryan Gahl Principal, Manager Nth Penguin, LLC - Consulting http://www.nthpenguin.com -- Software Architect WebWidgetry.com / MashupStudio.com Future Home of the World's First Complete Web Platform -- Inquire: 1-262-951-6727 Blog: http://www.someElement.com --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
> > I wasn't being very clear -- sorry. Those first two examples > > illustrate what would happen if we implemented *both* the stuff in the > > events branch as it is now *and* Dan's proposal to bind class methods > > automatically. > > Right! It is exactly where the magic bites. Heh, maybe your right. I think, as a JS programmer, that having to bind functions manually is what you expect to do but as a beginner it isn't but I suppose there's no point in confusing matters for experienced JS programmers. In the example here (where this is normally the element but if you pass in the a Class instance its bound to the object) I quite like how it works actually but each to their own. I still think it would be nicer if Class.create() actually created something that acted like a class from a class based language rather than just being a normal contructor. On that point about base: base.js doesn't bind methods but it does wrap every method to allow access to its super classes version of the method which is going to introduce even more of a performance overhead but hasn't been a problem in my experience. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
On 5/10/07, Andrew Dupont <[EMAIL PROTECTED]> wrote: > > > > The new Event code binds whatever it gets in IE to someElement. It > doesn't > > know anything about Foo. > > I wasn't being very clear -- sorry. Those first two examples > illustrate what would happen if we implemented *both* the stuff in the > events branch as it is now *and* Dan's proposal to bind class methods > automatically. Right! It is exactly where the magic bites. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
It's definitely not being cast off... Just scrutinized :-) -Original Message- From: "Dan Webb" <[EMAIL PROTECTED]> To: prototype-core@googlegroups.com Sent: 5/10/2007 11:52 AM Subject: [Prototype-core] Re: Class.create() and method binding > No, seriously - how often do people copy instance methods around? Is the > minority really enough to justify the mass binding on each instance > creation? How about solving the problem in a real way, by realizing what > you're doing an compensating for that: > > func = a.showA.bind(a) People do copy methods around without knowing it all the time: when assigning event handlers and using the enumerable methods most notably and this always causes confusion. Perhaps I didn't give real enough examples. MANY people try to do things like this and get very confused: var w = new MyWidget(); $('my_el').observe('click', w.someMethod); then find that this has changed in the context of the event handler. This is by no means an edge case: It happens all the time. Even when you know that this is the case and know about bind() it get really ugly as you find lots of places where you need bind and this would clean up a lot of those. My main point is that Class.create() does not create what anyone thinks of as a class. It's sort of looks like one but doesn't do anything that classes do. Why not make it behave more like a class? In Java, Ruby and just about all class-based languages methods have a binding to their instance. This would be mimicking that behavior. Plus, if you want the unbound version of the method you can get it from the prototype. I really don't think it's such a bad idea and I'm slightly surprised that you immediately cast it off. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
> Would it? ;) > > The new Event code binds whatever it gets in IE to someElement. It doesn't > know anything about Foo. I wasn't being very clear -- sorry. Those first two examples illustrate what would happen if we implemented *both* the stuff in the events branch as it is now *and* Dan's proposal to bind class methods automatically. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
On 5/10/07, Andrew Dupont <[EMAIL PROTECTED]> wrote: > > > ...but calling > > Event.observe(someElement, 'click', Foo.bar); > > (where bar is a function) would fire the event in Foo's scope. Would it? ;) The new Event code binds whatever it gets in IE to someElement. It doesn't know anything about Foo. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
Dan Webb wrote: > > It's not a bad cause, I just think the solution is a performance eater. > > Imagine: the loop runs on every object instantiation. It wraps every > > function inside another and it needs $A for that. After that, every function > > call internally calls another, triggering $A one more time. To me it's a > > terrible waste considering the total number of objects and their respective > > instance method calls. And for what, solving event handling gotchas? Surely > > we could do some implicit binding only in places where it makes sense (for > > instance in the Event or Ajax modules for some operations). > > Yeah, your right on that point. It was my main concern. It could be > streamlined a fair bit though (getting rid of $A would be fine) and I > wondered how many classes that are created with Class.create() really > get instantiated in a typical project. I'm interested to see the > impact it does have...I'll write some tests. I think you're right > though, it's probably not going to be worth the performance hit. > Saying that, I use base.js quite a bit which wraps functions in quite > a bit of code and I've not noticed the performance hit. My objection is not the performance hit -- it's violation of POLS. (Even though I do feel the pain this is meant to address.) The refurbished system in the events branch corrects scope automatically in IE, so that "this" refers to the element that received the action. This means that calling Event.observe(someElement, 'click', foo); (where foo is a function) would fire the event in someElement's scope, but calling Event.observe(someElement, 'click', Foo.bar); (where bar is a function) would fire the event in Foo's scope. I think that events firing in class scope should remain opt-in, whether through the existing `bind`: Event.observe(someElement, 'click', Foo.bar.bind(Foo)); or through an extra argument: Event.observe(someElement, 'click', Foo.bar, Foo); I prefer the latter, since it'd deprecate the useCapture argument (which won't work in IE, so we shouldn't expose it). In JavaScript, context binds in execution scope, not definition scope (though this will change for classes in ES4). I think we'd be stepping into a minefield if we introduced new "magic" conventions for what "this" means on any given line of code. It's hard enough to keep track of already. Cheers, Andrew --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
On 5/10/07, Dan Webb <[EMAIL PROTECTED]> wrote: > > > Yeah, your right on that point. It was my main concern. It could be > streamlined a fair bit though (getting rid of $A would be fine) Of course. $As aren't needed in this case. Saying that, I use base.js quite a bit which wraps functions in quite > a bit of code and I've not noticed the performance hit. Base *does* this? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
> It's not a bad cause, I just think the solution is a performance eater. > Imagine: the loop runs on every object instantiation. It wraps every > function inside another and it needs $A for that. After that, every function > call internally calls another, triggering $A one more time. To me it's a > terrible waste considering the total number of objects and their respective > instance method calls. And for what, solving event handling gotchas? Surely > we could do some implicit binding only in places where it makes sense (for > instance in the Event or Ajax modules for some operations). Yeah, your right on that point. It was my main concern. It could be streamlined a fair bit though (getting rid of $A would be fine) and I wondered how many classes that are created with Class.create() really get instantiated in a typical project. I'm interested to see the impact it does have...I'll write some tests. I think you're right though, it's probably not going to be worth the performance hit. Saying that, I use base.js quite a bit which wraps functions in quite a bit of code and I've not noticed the performance hit. Having scope stuff in observe is a very worthwhile and for the sake of compatibility with new versions of JS you should be able to pass an optional scope as the final argument to all of the enumerable functions. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
On 5/10/07, Dan Webb <[EMAIL PROTECTED]> wrote: > > > People do copy methods around without knowing it all the time: when > assigning event handlers and using the enumerable methods most notably > and this always causes confusion. Well, that's why we have bindAsEventListener(). I know it's a bit verbose - YUI does it internally, depending on an optional boolean attribute. Maybe we should do something like this in new Event stuff. I really don't think it's such a bad idea and I'm slightly surprised > that you immediately cast it off. It's not a bad cause, I just think the solution is a performance eater. Imagine: the loop runs on every object instantiation. It wraps everyfunction inside another and it needs $A for that. After that, every function call internally calls another, triggering $A one more time. To me it's a terrible waste considering the total number of objects and their respective instance method calls. And for what, solving event handling gotchas? Surely we could do some implicit binding only in places where it makes sense (for instance in the Event or Ajax modules for some operations). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
> No, seriously - how often do people copy instance methods around? Is the > minority really enough to justify the mass binding on each instance > creation? How about solving the problem in a real way, by realizing what > you're doing an compensating for that: > > func = a.showA.bind(a) People do copy methods around without knowing it all the time: when assigning event handlers and using the enumerable methods most notably and this always causes confusion. Perhaps I didn't give real enough examples. MANY people try to do things like this and get very confused: var w = new MyWidget(); $('my_el').observe('click', w.someMethod); then find that this has changed in the context of the event handler. This is by no means an edge case: It happens all the time. Even when you know that this is the case and know about bind() it get really ugly as you find lots of places where you need bind and this would clean up a lot of those. My main point is that Class.create() does not create what anyone thinks of as a class. It's sort of looks like one but doesn't do anything that classes do. Why not make it behave more like a class? In Java, Ruby and just about all class-based languages methods have a binding to their instance. This would be mimicking that behavior. Plus, if you want the unbound version of the method you can get it from the prototype. I really don't think it's such a bad idea and I'm slightly surprised that you immediately cast it off. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
On 5/10/07, Ryan Gahl <[EMAIL PROTECTED]> wrote: > > Yeah. What if I want to copy the instance method somewhere else, but I > > want it to change scope? If it was bound that I can't bind it to anything > > else. So it's a potential blocker in some cases. > > > Just what I was saying... > Mine had less underscores and uppercase :) I'm kidding - I just realized that you've said the same, when you pointed it out ... --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
> > Yeah. What if I want to copy the instance method somewhere else, but I > want it to change scope? If it was bound that I can't bind it to anything > else. So it's a potential blocker in some cases. Just what I was saying... --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
On 5/10/07, Dan Webb <[EMAIL PROTECTED]> wrote: > > > Any good? > It's awful :P No, seriously - how often do people copy instance methods around? Is the minority really enough to justify the mass binding on each instance creation? How about solving the problem in a real way, by realizing what you're doing an compensating for that: func = a.showA.bind(a) In my opinion, if you're doing something weird then go ahead, just be aware of the scope change and know how to handle it. Any problems Im not thinking of? Yeah. What if I want to copy the instance method somewhere else, but I want it to change scope? If it was bound that I can't bind it to anything else. So it's a potential blocker in some cases. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Class.create() and method binding
Interesting idea, and I'd have to really reflect on this... but my initial reaction is that it is actually somewhat limiting. Here's what I mean... In some edge cases it may desirable to use an instance method and bind it to _some_other_ object. This would certainly be considered "clever" and I can't think of any concrete cases right now, but I know with the way things are now it _possible_ if needed. Under this system you would be limiting the scope binding to only a single instance. I know what you're saying, in that that IS how traditional classes should be. HOWEVER, one of the things that makes js development so powerful is this dynamic nature, and the ability to do things like that when you need to. If this ability starts getting removed in a core layer of a major abstraction library like prototype, I think it may have potential to be a "bad thing". ...but that's just my initial reaction. Definitely seems like a reasonable thing for someone to propose though. I'll be interested to see how this one plays out... On 5/10/07, Dan Webb <[EMAIL PROTECTED]> wrote: > > > Hello Everyone, > > Just had an idea for a possible enhancement to Class.create() that I > wanted to float with y'all. Here's the preamble: > > From knocking around on mailing lists / IRC etc it seems that by far > the most irritating problem for most new JS library users is the idea > that, in JS, methods of objects have no inherent binding to the object > they are attached to so if you do something like this: > > Car = Class.create(); > Object.extend(Car.prototype, { > initialize : function(a) { >this.a = a; > }, > showA : function() { >console.log(this.a); > } > }); > > This gives the 'expected' result: > > a = new Car(7); > a.showA(); //=> 7 > > But this doesn't: > > func = a.showA > func(); //=> undefined > > This is always a problem inside event handlers and the enumerable > functions and of course the way to stop it is to use bind(). But I > think possibly that a point of confusion in Prototype particularly > that if you use Class.create() you expect a thing that acts like a > class which it of course doesn't. So > > How about this: > > Class = {}; > Class.create = function() { > return function() { >this.initialize.apply(this, arguments); > >for (var prop in this) > if (typeof this[prop] == 'function') >this[prop] = this[prop].bind(this); > }; > } > > Which also binds methods of the object to the object itself > automatically so you can point event handlers etc straight to methods > of objects and they remain bound? > > Any good? Any problems Im not thinking of? > > > > -- > Dan Webb > http://www.danwebb.net > > Event Wax (http://www.eventwax.com) > > > > -- Ryan Gahl Principal, Manager Nth Penguin, LLC - Consulting http://www.nthpenguin.com -- Software Architect WebWidgetry.com / MashupStudio.com Future Home of the World's First Complete Web Platform -- Inquire: 1-262-951-6727 Blog: http://www.someElement.com --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---