In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the declaration of the second object of class myClass alters the first object of the same class. However, it only alters ''this.options.value'', and not ''this.value''. Can you tell me why this behaviour occurs, and how to resolve it? Cheers --------------------------------------------------------------------------- var myClass = Class.create({ options:{}, value: false, initialize: function(options) { this.options.value = options.value; this.value = options.value; }, myAlert:function() { alert(this.options.value + '' : '' + this.value); } }); var classObj1 = new myClass({value:1}); classObj1.myAlert(); var classObj2 = new myClass({value:2}); classObj1.myAlert(); --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Ok, I''ve figured out that I can use this.options={} within the initialize function to declare defaults, and then follow this with ''Object.extend(this.options, options || {});'' to customise these defaults But I still don''t understand why I get different behaviour in the above example for this.options.value and this.value - can you tell me why? Thanks On Jan 17, 4:30 pm, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > declaration of the second object of class myClass alters the first > object of the same class. However, it only alters > ''this.options.value'', and not ''this.value''. Can you tell me why this > behaviour occurs, and how to resolve it? > > Cheers > > --------------------------------------------------------------------------- > var myClass = Class.create({ > options:{}, > value: false, > initialize: function(options) { > this.options.value = options.value; > this.value = options.value; > }, > myAlert:function() { > alert(this.options.value + '' : '' + this.value); > } > > }); > > var classObj1 = new myClass({value:1}); > classObj1.myAlert(); > var classObj2 = new myClass({value:2}); > classObj1.myAlert();--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Snook has a pretty good explanation: http://snook.ca/archives/javascript/javascript_pass/ Best, Tobie On Jan 17, 5:54 pm, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Ok, I''ve figured out that I can use this.options={} within the > initialize function to declare defaults, and then follow this with > ''Object.extend(this.options, options || {});'' to customise these > defaults > > But I still don''t understand why I get different behaviour in the > above example for this.options.value and this.value - can you tell me > why? > > Thanks > > On Jan 17, 4:30 pm, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > > declaration of the second object of class myClass alters the first > > object of the same class. However, it only alters > > ''this.options.value'', and not ''this.value''. Can you tell me why this > > behaviour occurs, and how to resolve it? > > > Cheers > > > --------------------------------------------------------------------------- > > var myClass = Class.create({ > > options:{}, > > value: false, > > initialize: function(options) { > > this.options.value = options.value; > > this.value = options.value; > > }, > > myAlert:function() { > > alert(this.options.value + '' : '' + this.value); > > } > > > }); > > > var classObj1 = new myClass({value:1}); > > classObj1.myAlert(); > > var classObj2 = new myClass({value:2}); > > classObj1.myAlert();--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
I''d actually looked at Snook''s article, but hadn''t managed to find an answer from it. Either I didn''t get it, or my problem doesn''t actually involve an issue with passing values by reference/value - I''m not sure which. On Jan 17, 5:02 pm, Tobie Langel <tobie.lan...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Snook has a pretty good explanation:http://snook.ca/archives/javascript/javascript_pass/ > > Best, > > Tobie > > On Jan 17, 5:54 pm, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Ok, I''ve figured out that I can use this.options={} within the > > initialize function to declare defaults, and then follow this with > > ''Object.extend(this.options, options || {});'' to customise these > > defaults > > > But I still don''t understand why I get different behaviour in the > > above example for this.options.value and this.value - can you tell me > > why? > > > Thanks > > > On Jan 17, 4:30 pm, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > > > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > > > declaration of the second object of class myClass alters the first > > > object of the same class. However, it only alters > > > ''this.options.value'', and not ''this.value''. Can you tell me why this > > > behaviour occurs, and how to resolve it? > > > > Cheers > > > > --------------------------------------------------------------------------- > > > var myClass = Class.create({ > > > options:{}, > > > value: false, > > > initialize: function(options) { > > > this.options.value = options.value; > > > this.value = options.value; > > > }, > > > myAlert:function() { > > > alert(this.options.value + '' : '' + this.value); > > > } > > > > }); > > > > var classObj1 = new myClass({value:1}); > > > classObj1.myAlert(); > > > var classObj2 = new myClass({value:2}); > > > classObj1.myAlert();--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
iporter wrote:> ...var myClass = Class.create({ > options:{}, > value: false, > initialize: function(options) { > this.options.value = options.value; > this.value = options.value; > }, > myAlert:function() { > alert(this.options.value + '' : '' + this.value); > } > }); > > var classObj1 = new myClass({value:1}); > classObj1.myAlert(); > var classObj2 = new myClass({value:2}); > classObj1.myAlert(); > >What you''re missing is the fact that myClass.prototype.options will be shared across all instances the same way myClass.options would be. In JS, objects (and arrays) are always passed by reference. This class construction behavior is quite different than the behavior of true OO languages. In JS, it is best to always initialize instance properties inside of functions. Try the code below. - Ken Snyder var myClass = Class.create({ initialize: function(options) { this.options = {}; this.value = false; this.options.value = options.value; this.value = options.value; }, myAlert: function() { alert(this.options.value + '' : '' + this.value); } }); var classObj1 = new myClass({value:1}); classObj1.myAlert(); // 1 : 1 var classObj2 = new myClass({value:2}); classObj1.myAlert(); // 1 : 1 classObj2.myAlert(); // 2 : 2 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On Jan 18, 2:30 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > declaration of the second object of class myClass alters the first > object of the same class. However, it only alters > ''this.options.value'', and not ''this.value''. Can you tell me why this > behaviour occurs, and how to resolve it? > > Cheers > > --------------------------------------------------------------------------- > var myClass = Class.create({ > options:{}, > value: false, > initialize: function(options) { > this.options.value = options.value; > this.value = options.value; > }, > myAlert:function() { > alert(this.options.value + '' : '' + this.value); > } > > }); > > var classObj1 = new myClass({value:1}); > classObj1.myAlert(); > var classObj2 = new myClass({value:2}); > classObj1.myAlert();I think you are better off to understand what is actually happening. Javascript does not have classes - it isn''t an object oriented language, it''s object based. It uses prototypes for inheritance, not classic OO inheritance. While you can paper over the differences, they are still there. Two features that often cause issues are the this keyword and closures, which have combined here to cause an unexpected result. To write your "class" (it''s actually a javascript constructor, but whatever) using plain javascript, you would write something like: function MyClass(obj) { this.value = obj.value; } MyClass.prototype.options = {}; MyClass.prototype.showValue = function(){ alert(this.options.value + '':'' + this.value); } That''s it. Note that this takes less code than using Class.create(). Now if you test this: var x = new MyClass({value:1}); x.showValue(); // --> 1:1 var y = new MyClass({value:2}); x.showValue(); // --> 2:1 You get the result you didn''t want - the options object is shared by all instances of MyClass because it is a property of the constructor''s prototype. If you want each instance of MyClass to have its own options object, you add it in the constructor: function MyClass(obj) { this.value = obj.value; this.options = {}; this.options.value = this.value; // or obj.value; } MyClass.prototype.showValue = function(){ alert(this.options.value + '':'' + this.value); } Now when you create some instances: var x = new MyClass({value:1}); x.showValue(); // --> 1:1 var y = new MyClass({value:2}); x.showValue(); // --> 1:1 y.showValue(); // --> 2:2 Is that what you wanted? To me, the above is much simpler and clearer than using Class.create, and is less code. -- Rob --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Rob, that''s a great explanation, thanks. You''re right, I see now how using the prototype keyword makes it clearer what is part of the class, and what is part of the instance. In the below example, I have to put the instruction to create the behaviours of the Man and Woman in each of their constructors. However, Man and Woman are both subclasses of the Person class - how can I get this instruction into the Person class? Cheers again! ---------------------------------------------------------------------------- var Behaviours = Class.create({ initialize: function() { this.array=[]; }, push: function(behaviour) { this.array.push(behaviour); }, list: function() { $A(this.array).each(function(behaviour) { alert(behaviour); }); } }); var Person = Class.create({}); var Man = Class.create(Person, { initialize: function () { this.name = ''Iain''; this.behaviours = new Behaviours(); this.behaviours.push(''eat''); } }); var Woman = Class.create(Person, { initialize: function () { this.name = ''Ailsa''; this.behaviours = new Behaviours(); this.behaviours.push(''talk''); } }); On Jan 18, 7:13 am, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote:> On Jan 18, 2:30 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > > declaration of the second object of class myClass alters the first > > object of the same class. However, it only alters > > ''this.options.value'', and not ''this.value''. Can you tell me why this > > behaviour occurs, and how to resolve it? > > > Cheers > > > --------------------------------------------------------------------------- > > var myClass = Class.create({ > > options:{}, > > value: false, > > initialize: function(options) { > > this.options.value = options.value; > > this.value = options.value; > > }, > > myAlert:function() { > > alert(this.options.value + '' : '' + this.value); > > } > > > }); > > > var classObj1 = new myClass({value:1}); > > classObj1.myAlert(); > > var classObj2 = new myClass({value:2}); > > classObj1.myAlert(); > > I think you are better off to understand what is actually happening. > Javascript does not have classes - it isn''t an object oriented > language, it''s object based. It uses prototypes for inheritance, not > classic OO inheritance. > > While you can paper over the differences, they are still there. Two > features that often cause issues are the this keyword and closures, > which have combined here to cause an unexpected result. > > To write your "class" (it''s actually a javascript constructor, but > whatever) using plain javascript, you would write something like: > > function MyClass(obj) { > this.value = obj.value;} > > MyClass.prototype.options = {}; > MyClass.prototype.showValue = function(){ > alert(this.options.value + '':'' + this.value); > > } > > That''s it. Note that this takes less code than using Class.create(). > Now if you test this: > > var x = new MyClass({value:1}); > x.showValue(); // --> 1:1 > > var y = new MyClass({value:2}); > x.showValue(); // --> 2:1 > > You get the result you didn''t want - the options object is shared by > all instances of MyClass because it is a property of the constructor''s > prototype. If you want each instance of MyClass to have its own > options object, you add it in the constructor: > > function MyClass(obj) { > this.value = obj.value; > this.options = {}; > this.options.value = this.value; // or obj.value;} > > MyClass.prototype.showValue = function(){ > alert(this.options.value + '':'' + this.value); > > } > > Now when you create some instances: > > var x = new MyClass({value:1}); > x.showValue(); // --> 1:1 > > var y = new MyClass({value:2}); > x.showValue(); // --> 1:1 > y.showValue(); // --> 2:2 > > Is that what you wanted? To me, the above is much simpler and clearer > than using Class.create, and is less code. > > -- > Rob--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Richard Quadling
2008-Jan-19 11:04 UTC
Re: Passing by Reference / Value - Simple OO Problem
On 19/01/2008, iporter <isporter-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Rob, that''s a great explanation, thanks. You''re right, I see now how > using the prototype keyword makes it clearer what is part of the > class, and what is part of the instance. > > In the below example, I have to put the instruction to create the > behaviours of the Man and Woman in each of their constructors. > However, Man and Woman are both subclasses of the Person class - how > can I get this instruction into the Person class? > > Cheers again! > > ---------------------------------------------------------------------------- > var Behaviours = Class.create({ > initialize: function() { > this.array=[]; > }, > push: function(behaviour) { > this.array.push(behaviour); > }, > list: function() { > $A(this.array).each(function(behaviour) { > alert(behaviour); > }); > } > }); > > var Person = Class.create({}); > > var Man = Class.create(Person, { > initialize: function () { > this.name = ''Iain''; > this.behaviours = new Behaviours(); > this.behaviours.push(''eat''); > } > }); > > var Woman = Class.create(Person, { > initialize: function () { > this.name = ''Ailsa''; > this.behaviours = new Behaviours(); > this.behaviours.push(''talk''); > } > }); > > > On Jan 18, 7:13 am, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote: > > On Jan 18, 2:30 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > > > > In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > > > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > > > declaration of the second object of class myClass alters the first > > > object of the same class. However, it only alters > > > ''this.options.value'', and not ''this.value''. Can you tell me why this > > > behaviour occurs, and how to resolve it? > > > > > Cheers > > > > > --------------------------------------------------------------------------- > > > var myClass = Class.create({ > > > options:{}, > > > value: false, > > > initialize: function(options) { > > > this.options.value = options.value; > > > this.value = options.value; > > > }, > > > myAlert:function() { > > > alert(this.options.value + '' : '' + this.value); > > > } > > > > > }); > > > > > var classObj1 = new myClass({value:1}); > > > classObj1.myAlert(); > > > var classObj2 = new myClass({value:2}); > > > classObj1.myAlert(); > > > > I think you are better off to understand what is actually happening. > > Javascript does not have classes - it isn''t an object oriented > > language, it''s object based. It uses prototypes for inheritance, not > > classic OO inheritance. > > > > While you can paper over the differences, they are still there. Two > > features that often cause issues are the this keyword and closures, > > which have combined here to cause an unexpected result. > > > > To write your "class" (it''s actually a javascript constructor, but > > whatever) using plain javascript, you would write something like: > > > > function MyClass(obj) { > > this.value = obj.value;} > > > > MyClass.prototype.options = {}; > > MyClass.prototype.showValue = function(){ > > alert(this.options.value + '':'' + this.value); > > > > } > > > > That''s it. Note that this takes less code than using Class.create(). > > Now if you test this: > > > > var x = new MyClass({value:1}); > > x.showValue(); // --> 1:1 > > > > var y = new MyClass({value:2}); > > x.showValue(); // --> 2:1 > > > > You get the result you didn''t want - the options object is shared by > > all instances of MyClass because it is a property of the constructor''s > > prototype. If you want each instance of MyClass to have its own > > options object, you add it in the constructor: > > > > function MyClass(obj) { > > this.value = obj.value; > > this.options = {}; > > this.options.value = this.value; // or obj.value;} > > > > MyClass.prototype.showValue = function(){ > > alert(this.options.value + '':'' + this.value); > > > > } > > > > Now when you create some instances: > > > > var x = new MyClass({value:1}); > > x.showValue(); // --> 1:1 > > > > var y = new MyClass({value:2}); > > x.showValue(); // --> 1:1 > > y.showValue(); // --> 2:2 > > > > Is that what you wanted? To me, the above is much simpler and clearer > > than using Class.create, and is less code. > > > > -- > > Rob > > >Take a look at $super. http://prototypejs.org/api/class/create and the example of subclassing the Animal into a Snake. -- ----- Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731 "Standing on the shoulders of some very clever giants!" --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Yup, just found that. So, looks like I''m back on track and need to start over with how I build my objects up - thanks all for your help. On Jan 19, 11:04 am, "Richard Quadling" <rquadl...-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote:> On 19/01/2008, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > > Rob, that''s a great explanation, thanks. You''re right, I see now how > > using the prototype keyword makes it clearer what is part of the > > class, and what is part of the instance. > > > In the below example, I have to put the instruction to create the > > behaviours of the Man and Woman in each of their constructors. > > However, Man and Woman are both subclasses of the Person class - how > > can I get this instruction into the Person class? > > > Cheers again! > > > ---------------------------------------------------------------------------- > > var Behaviours = Class.create({ > > initialize: function() { > > this.array=[]; > > }, > > push: function(behaviour) { > > this.array.push(behaviour); > > }, > > list: function() { > > $A(this.array).each(function(behaviour) { > > alert(behaviour); > > }); > > } > > }); > > > var Person = Class.create({}); > > > var Man = Class.create(Person, { > > initialize: function () { > > this.name = ''Iain''; > > this.behaviours = new Behaviours(); > > this.behaviours.push(''eat''); > > } > > }); > > > var Woman = Class.create(Person, { > > initialize: function () { > > this.name = ''Ailsa''; > > this.behaviours = new Behaviours(); > > this.behaviours.push(''talk''); > > } > > }); > > > On Jan 18, 7:13 am, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote: > > > On Jan 18, 2:30 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > > > > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > > > > declaration of the second object of class myClass alters the first > > > > object of the same class. However, it only alters > > > > ''this.options.value'', and not ''this.value''. Can you tell me why this > > > > behaviour occurs, and how to resolve it? > > > > > Cheers > > > > > --------------------------------------------------------------------------- > > > > var myClass = Class.create({ > > > > options:{}, > > > > value: false, > > > > initialize: function(options) { > > > > this.options.value = options.value; > > > > this.value = options.value; > > > > }, > > > > myAlert:function() { > > > > alert(this.options.value + '' : '' + this.value); > > > > } > > > > > }); > > > > > var classObj1 = new myClass({value:1}); > > > > classObj1.myAlert(); > > > > var classObj2 = new myClass({value:2}); > > > > classObj1.myAlert(); > > > > I think you are better off to understand what is actually happening. > > > Javascript does not have classes - it isn''t an object oriented > > > language, it''s object based. It uses prototypes for inheritance, not > > > classic OO inheritance. > > > > While you can paper over the differences, they are still there. Two > > > features that often cause issues are the this keyword and closures, > > > which have combined here to cause an unexpected result. > > > > To write your "class" (it''s actually a javascript constructor, but > > > whatever) using plain javascript, you would write something like: > > > > function MyClass(obj) { > > > this.value = obj.value;} > > > > MyClass.prototype.options = {}; > > > MyClass.prototype.showValue = function(){ > > > alert(this.options.value + '':'' + this.value); > > > > } > > > > That''s it. Note that this takes less code than using Class.create(). > > > Now if you test this: > > > > var x = new MyClass({value:1}); > > > x.showValue(); // --> 1:1 > > > > var y = new MyClass({value:2}); > > > x.showValue(); // --> 2:1 > > > > You get the result you didn''t want - the options object is shared by > > > all instances of MyClass because it is a property of the constructor''s > > > prototype. If you want each instance of MyClass to have its own > > > options object, you add it in the constructor: > > > > function MyClass(obj) { > > > this.value = obj.value; > > > this.options = {}; > > > this.options.value = this.value; // or obj.value;} > > > > MyClass.prototype.showValue = function(){ > > > alert(this.options.value + '':'' + this.value); > > > > } > > > > Now when you create some instances: > > > > var x = new MyClass({value:1}); > > > x.showValue(); // --> 1:1 > > > > var y = new MyClass({value:2}); > > > x.showValue(); // --> 1:1 > > > y.showValue(); // --> 2:2 > > > > Is that what you wanted? To me, the above is much simpler and clearer > > > than using Class.create, and is less code. > > > > -- > > > Rob > > Take a look at $super.http://prototypejs.org/api/class/createand the > example of subclassing the Animal into a Snake. > > -- > ----- > Richard Quadling > Zend Certified Engineer :http://zend.com/zce.php?c=ZEND002498&r=213474731 > "Standing on the shoulders of some very clever giants!"--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Rob, I think I''m going to use the class.prototype.method syntax. I''m pretty sure it''s still more verbose, but I want to use the same class definitions in the same .js file on the client and server sides, and it seems I can''t if the class is a global variable, instead of a function (see http://groups.google.com/group/rubyonrails-spinoffs/browse_frm/thread/62c82c16ef7c7c6c/991e66b3aee31d76#991e66b3aee31d76 if interested). How does one acheive the effect of $super if not using Prototype''s Class class? Cheers, Iain On Jan 18, 7:13 am, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote:> On Jan 18, 2:30 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > > declaration of the second object of class myClass alters the first > > object of the same class. However, it only alters > > ''this.options.value'', and not ''this.value''. Can you tell me why this > > behaviour occurs, and how to resolve it? > > > Cheers > > > --------------------------------------------------------------------------- > > var myClass = Class.create({ > > options:{}, > > value: false, > > initialize: function(options) { > > this.options.value = options.value; > > this.value = options.value; > > }, > > myAlert:function() { > > alert(this.options.value + '' : '' + this.value); > > } > > > }); > > > var classObj1 = new myClass({value:1}); > > classObj1.myAlert(); > > var classObj2 = new myClass({value:2}); > > classObj1.myAlert(); > > I think you are better off to understand what is actually happening. > Javascript does not have classes - it isn''t an object oriented > language, it''s object based. It uses prototypes for inheritance, not > classic OO inheritance. > > While you can paper over the differences, they are still there. Two > features that often cause issues are the this keyword and closures, > which have combined here to cause an unexpected result. > > To write your "class" (it''s actually a javascript constructor, but > whatever) using plain javascript, you would write something like: > > function MyClass(obj) { > this.value = obj.value;} > > MyClass.prototype.options = {}; > MyClass.prototype.showValue = function(){ > alert(this.options.value + '':'' + this.value); > > } > > That''s it. Note that this takes less code than using Class.create(). > Now if you test this: > > var x = new MyClass({value:1}); > x.showValue(); // --> 1:1 > > var y = new MyClass({value:2}); > x.showValue(); // --> 2:1 > > You get the result you didn''t want - the options object is shared by > all instances of MyClass because it is a property of the constructor''s > prototype. If you want each instance of MyClass to have its own > options object, you add it in the constructor: > > function MyClass(obj) { > this.value = obj.value; > this.options = {}; > this.options.value = this.value; // or obj.value;} > > MyClass.prototype.showValue = function(){ > alert(this.options.value + '':'' + this.value); > > } > > Now when you create some instances: > > var x = new MyClass({value:1}); > x.showValue(); // --> 1:1 > > var y = new MyClass({value:2}); > x.showValue(); // --> 1:1 > y.showValue(); // --> 2:2 > > Is that what you wanted? To me, the above is much simpler and clearer > than using Class.create, and is less code. > > -- > Rob--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Ok, I think I got it (if the indentation''s funky, it''s just so I can collapse functions and they line up, so I still get a sense of where classes start and end, as I had with the Class.create method): function Behaviours () { this.array = []; } Behaviours.prototype.push = function (behaviour) { this.array.push(behaviour); } Behaviours.prototype.list = function () { $A(this.array).each(function(behaviour) { alert(behaviour); }); } function Person(name) { this.name = name; this.behaviours = new Behaviours(); } function Man (name) { Person(name); this.behaviours.push(''eat''); } Man.prototype = new Person(); function Woman (name) { Person(name); this.behaviours.push(''talk''); } Woman.prototype = new Person(); On Jan 19, 11:27 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Rob, I think I''m going to use the class.prototype.method syntax. I''m > pretty sure it''s still more verbose, but I want to use the same class > definitions in the same .js file on the client and server sides, and > it seems I can''t if the class is a global variable, instead of a > function (seehttp://groups.google.com/group/rubyonrails-spinoffs/browse_frm/thread... > if interested). > > How does one acheive the effect of $super if not using Prototype''s > Class class? > > Cheers, > Iain > > On Jan 18, 7:13 am, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote: > > > On Jan 18, 2:30 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > > > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > > > declaration of the second object of class myClass alters the first > > > object of the same class. However, it only alters > > > ''this.options.value'', and not ''this.value''. Can you tell me why this > > > behaviour occurs, and how to resolve it? > > > > Cheers > > > > --------------------------------------------------------------------------- > > > var myClass = Class.create({ > > > options:{}, > > > value: false, > > > initialize: function(options) { > > > this.options.value = options.value; > > > this.value = options.value; > > > }, > > > myAlert:function() { > > > alert(this.options.value + '' : '' + this.value); > > > } > > > > }); > > > > var classObj1 = new myClass({value:1}); > > > classObj1.myAlert(); > > > var classObj2 = new myClass({value:2}); > > > classObj1.myAlert(); > > > I think you are better off to understand what is actually happening. > > Javascript does not have classes - it isn''t an object oriented > > language, it''s object based. It uses prototypes for inheritance, not > > classic OO inheritance. > > > While you can paper over the differences, they are still there. Two > > features that often cause issues are the this keyword and closures, > > which have combined here to cause an unexpected result. > > > To write your "class" (it''s actually a javascript constructor, but > > whatever) using plain javascript, you would write something like: > > > function MyClass(obj) { > > this.value = obj.value;} > > > MyClass.prototype.options = {}; > > MyClass.prototype.showValue = function(){ > > alert(this.options.value + '':'' + this.value); > > > } > > > That''s it. Note that this takes less code than using Class.create(). > > Now if you test this: > > > var x = new MyClass({value:1}); > > x.showValue(); // --> 1:1 > > > var y = new MyClass({value:2}); > > x.showValue(); // --> 2:1 > > > You get the result you didn''t want - the options object is shared by > > all instances of MyClass because it is a property of the constructor''s > > prototype. If you want each instance of MyClass to have its own > > options object, you add it in the constructor: > > > function MyClass(obj) { > > this.value = obj.value; > > this.options = {}; > > this.options.value = this.value; // or obj.value;} > > > MyClass.prototype.showValue = function(){ > > alert(this.options.value + '':'' + this.value); > > > } > > > Now when you create some instances: > > > var x = new MyClass({value:1}); > > x.showValue(); // --> 1:1 > > > var y = new MyClass({value:2}); > > x.showValue(); // --> 1:1 > > y.showValue(); // --> 2:2 > > > Is that what you wanted? To me, the above is much simpler and clearer > > than using Class.create, and is less code. > > > -- > > Rob--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Nope - I got it wrong, sorry! Replace Person(name); in the subclasses with Person.call(this, name); On Jan 19, 11:44 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Ok, I think I got it (if the indentation''s funky, it''s just so I can > collapse functions and they line up, so I still get a sense of where > classes start and end, as I had with the Class.create method): > > function Behaviours () { > this.array = []; > } > Behaviours.prototype.push = function (behaviour) { > this.array.push(behaviour); > } > Behaviours.prototype.list = function () { > $A(this.array).each(function(behaviour) { > alert(behaviour); > }); > } > > function Person(name) { > this.name = name; > this.behaviours = new Behaviours(); > } > > function Man (name) { > Person(name); > this.behaviours.push(''eat''); > } > Man.prototype = new Person(); > > function Woman (name) { > Person(name); > this.behaviours.push(''talk''); > } > Woman.prototype = new Person(); > > On Jan 19, 11:27 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Rob, I think I''m going to use the class.prototype.method syntax. I''m > > pretty sure it''s still more verbose, but I want to use the same class > > definitions in the same .js file on the client and server sides, and > > it seems I can''t if the class is a global variable, instead of a > > function (seehttp://groups.google.com/group/rubyonrails-spinoffs/browse_frm/thread... > > if interested). > > > How does one acheive the effect of $super if not using Prototype''s > > Class class? > > > Cheers, > > Iain > > > On Jan 18, 7:13 am, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote: > > > > On Jan 18, 2:30 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > > > > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > > > > declaration of the second object of class myClass alters the first > > > > object of the same class. However, it only alters > > > > ''this.options.value'', and not ''this.value''. Can you tell me why this > > > > behaviour occurs, and how to resolve it? > > > > > Cheers > > > > > --------------------------------------------------------------------------- > > > > var myClass = Class.create({ > > > > options:{}, > > > > value: false, > > > > initialize: function(options) { > > > > this.options.value = options.value; > > > > this.value = options.value; > > > > }, > > > > myAlert:function() { > > > > alert(this.options.value + '' : '' + this.value); > > > > } > > > > > }); > > > > > var classObj1 = new myClass({value:1}); > > > > classObj1.myAlert(); > > > > var classObj2 = new myClass({value:2}); > > > > classObj1.myAlert(); > > > > I think you are better off to understand what is actually happening. > > > Javascript does not have classes - it isn''t an object oriented > > > language, it''s object based. It uses prototypes for inheritance, not > > > classic OO inheritance. > > > > While you can paper over the differences, they are still there. Two > > > features that often cause issues are the this keyword and closures, > > > which have combined here to cause an unexpected result. > > > > To write your "class" (it''s actually a javascript constructor, but > > > whatever) using plain javascript, you would write something like: > > > > function MyClass(obj) { > > > this.value = obj.value;} > > > > MyClass.prototype.options = {}; > > > MyClass.prototype.showValue = function(){ > > > alert(this.options.value + '':'' + this.value); > > > > } > > > > That''s it. Note that this takes less code than using Class.create(). > > > Now if you test this: > > > > var x = new MyClass({value:1}); > > > x.showValue(); // --> 1:1 > > > > var y = new MyClass({value:2}); > > > x.showValue(); // --> 2:1 > > > > You get the result you didn''t want - the options object is shared by > > > all instances of MyClass because it is a property of the constructor''s > > > prototype. If you want each instance of MyClass to have its own > > > options object, you add it in the constructor: > > > > function MyClass(obj) { > > > this.value = obj.value; > > > this.options = {}; > > > this.options.value = this.value; // or obj.value;} > > > > MyClass.prototype.showValue = function(){ > > > alert(this.options.value + '':'' + this.value); > > > > } > > > > Now when you create some instances: > > > > var x = new MyClass({value:1}); > > > x.showValue(); // --> 1:1 > > > > var y = new MyClass({value:2}); > > > x.showValue(); // --> 1:1 > > > y.showValue(); // --> 2:2 > > > > Is that what you wanted? To me, the above is much simpler and clearer > > > than using Class.create, and is less code. > > > > -- > > > Rob--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Nope, I still don''t have it. In the below code, the behaviours object is shared between all the popup objects :0( If I declare it in the Popup() function, it works properly - but I want to declare it in complexDOM, since all complexDOM''s will have behaviours. Any pointers? function Behaviours () { this.array = new Array(); } Behaviours.prototype.push(el, event, method) = function() { this.array.push({el, event, method}); } function complexDOM () { this.behaviours = new Behaviours(); } function Popup () { this.options... } Popup.prototype = new complexDOM(); I also found that I was unable to use the below - when trying to loop through this in the list function, this wasn''t an array: function Behaviours () {} Behaviours.prototype = new Array(); Behaviours.prototype.list = function() { this.each(function(behaviour) {...}); } Cheers. On Jan 19, 12:27 pm, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Nope - I got it wrong, sorry! Replace Person(name); in the subclasses > with Person.call(this, name); > > On Jan 19, 11:44 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Ok, I think I got it (if the indentation''s funky, it''s just so I can > > collapse functions and they line up, so I still get a sense of where > > classes start and end, as I had with the Class.create method): > > > function Behaviours () { > > this.array = []; > > } > > Behaviours.prototype.push = function (behaviour) { > > this.array.push(behaviour); > > } > > Behaviours.prototype.list = function () { > > $A(this.array).each(function(behaviour) { > > alert(behaviour); > > }); > > } > > > function Person(name) { > > this.name = name; > > this.behaviours = new Behaviours(); > > } > > > function Man (name) { > > Person(name); > > this.behaviours.push(''eat''); > > } > > Man.prototype = new Person(); > > > function Woman (name) { > > Person(name); > > this.behaviours.push(''talk''); > > } > > Woman.prototype = new Person(); > > > On Jan 19, 11:27 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > Rob, I think I''m going to use the class.prototype.method syntax. I''m > > > pretty sure it''s still more verbose, but I want to use the same class > > > definitions in the same .js file on the client and server sides, and > > > it seems I can''t if the class is a global variable, instead of a > > > function (seehttp://groups.google.com/group/rubyonrails-spinoffs/browse_frm/thread... > > > if interested). > > > > How does one acheive the effect of $super if not using Prototype''s > > > Class class? > > > > Cheers, > > > Iain > > > > On Jan 18, 7:13 am, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote: > > > > > On Jan 18, 2:30 am, iporter <ispor...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > In the below code, I expect two alerts ''1 : 1'' and then ''1 : 1'', but > > > > > in reality I get ''1 : 1'' and ''2 : 1''. For some reason, the > > > > > declaration of the second object of class myClass alters the first > > > > > object of the same class. However, it only alters > > > > > ''this.options.value'', and not ''this.value''. Can you tell me why this > > > > > behaviour occurs, and how to resolve it? > > > > > > Cheers > > > > > > --------------------------------------------------------------------------- > > > > > var myClass = Class.create({ > > > > > options:{}, > > > > > value: false, > > > > > initialize: function(options) { > > > > > this.options.value = options.value; > > > > > this.value = options.value; > > > > > }, > > > > > myAlert:function() { > > > > > alert(this.options.value + '' : '' + this.value); > > > > > } > > > > > > }); > > > > > > var classObj1 = new myClass({value:1}); > > > > > classObj1.myAlert(); > > > > > var classObj2 = new myClass({value:2}); > > > > > classObj1.myAlert(); > > > > > I think you are better off to understand what is actually happening. > > > > Javascript does not have classes - it isn''t an object oriented > > > > language, it''s object based. It uses prototypes for inheritance, not > > > > classic OO inheritance. > > > > > While you can paper over the differences, they are still there. Two > > > > features that often cause issues are the this keyword and closures, > > > > which have combined here to cause an unexpected result. > > > > > To write your "class" (it''s actually a javascript constructor, but > > > > whatever) using plain javascript, you would write something like: > > > > > function MyClass(obj) { > > > > this.value = obj.value;} > > > > > MyClass.prototype.options = {}; > > > > MyClass.prototype.showValue = function(){ > > > > alert(this.options.value + '':'' + this.value); > > > > > } > > > > > That''s it. Note that this takes less code than using Class.create(). > > > > Now if you test this: > > > > > var x = new MyClass({value:1}); > > > > x.showValue(); // --> 1:1 > > > > > var y = new MyClass({value:2}); > > > > x.showValue(); // --> 2:1 > > > > > You get the result you didn''t want - the options object is shared by > > > > all instances of MyClass because it is a property of the constructor''s > > > > prototype. If you want each instance of MyClass to have its own > > > > options object, you add it in the constructor: > > > > > function MyClass(obj) { > > > > this.value = obj.value; > > > > this.options = {}; > > > > this.options.value = this.value; // or obj.value;} > > > > > MyClass.prototype.showValue = function(){ > > > > alert(this.options.value + '':'' + this.value); > > > > > } > > > > > Now when you create some instances: > > > > > var x = new MyClass({value:1}); > > > > x.showValue(); // --> 1:1 > > > > > var y = new MyClass({value:2}); > > > > x.showValue(); // --> 1:1 > > > > y.showValue(); // --> 2:2 > > > > > Is that what you wanted? To me, the above is much simpler and clearer > > > > than using Class.create, and is less code. > > > > > -- > > > > Rob--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---