Prev: How to link CSS(s) already linked to parent frame into child iframe using javascript
Next: Error getElementbyClassName
From: Asen Bozhilov on 14 Jan 2010 16:13 Dmitry A. Soshnikov wrote: > If to mark each method with `name' property (which is used in > Spidermonkey) - it's possible to use simply `this._super()' to call > parent method with the same name, and `this._super(anyOtherName)' to > call other parent method. That's what I was talking about using > `caller' for that. I modified my example for your purposes. Again i use full power of the language: function Base(){} Base.prototype._super = function() { var proto = this._proto, parent = proto._parent, func = parent[arguments.callee.caller._name] || proto.constructor; delete proto._parent; delete proto._proto; func.apply(this, arguments); proto._parent = parent; proto._proto = proto; }; Base.prototype.methods = function(methods) { for (var i in methods) { if (methods.hasOwnProperty(i)) { var f = methods[i]; f._name = i; this[i] = f; } } }; Object.extend = (function() { function F(){} return function(construct, parentConstruct) { F.prototype = parentConstruct.prototype; var p = construct.prototype = new F(); p.constructor = construct; p._proto = p; p._parent = parentConstruct.prototype; }; })(); /*Example*/ function A() { this.a_construct = 1; } Object.extend(A, Base); A.prototype.methods({ test : function() { this.a_test = 1; this._super(); } }); function B() { this.b_construct = 2; this._super(); } Object.extend(B, A); B.prototype.methods({ test : function() { this.b_test = 2; this._super(); } }); function C() { this.c_construct = 3; this._super(); } Object.extend(C, B); C.prototype.methods({ test : function() { this.c_test = 3; this._super(); } }); var o = new C(); window.alert(o.a_construct); //1 window.alert(o.b_construct); //2 window.alert(o.c_construct); //3 o.test(); window.alert(o.a_test); //1 window.alert(o.b_test); //2 window.alert(o.c_test); //3 Inherit from Base.prototype and you can use syntactic sugar `this._super()'. I like much more my previous version with, `name' argument, but that examples is for someone who want syntactic sugar in way discussed here. Regards.
From: Dmitry A. Soshnikov on 15 Jan 2010 04:35 On Jan 15, 12:13 am, Asen Bozhilov <asen.bozhi...(a)gmail.com> wrote: > Dmitry A. Soshnikov wrote: > > If to mark each method with `name' property (which is used in > > Spidermonkey) - it's possible to use simply `this._super()' to call > > parent method with the same name, and `this._super(anyOtherName)' to > > call other parent method. That's what I was talking about using > > `caller' for that. > > I modified my example for your purposes. Again i use full power of the > language: > > function Base(){} > Base.prototype._super = function() > { > var proto = this._proto, > parent = proto._parent, > func = parent[arguments.callee.caller._name] || proto.constructor; > delete proto._parent; > delete proto._proto; > func.apply(this, arguments); > proto._parent = parent; > proto._proto = proto; > > }; > > Base.prototype.methods = function(methods) { > for (var i in methods) > { > if (methods.hasOwnProperty(i)) > { > var f = methods[i]; > f._name = i; > this[i] = f; > } > } > > }; > > Object.extend = (function() > { > function F(){} > return function(construct, parentConstruct) > { > F.prototype = parentConstruct.prototype; > var p = construct.prototype = new F(); > p.constructor = construct; > p._proto = p; > p._parent = parentConstruct.prototype; > }; > > })(); > > /*Example*/ > function A() > { > this.a_construct = 1;} > > Object.extend(A, Base); > A.prototype.methods({ > test : function() > { > this.a_test = 1; > this._super(); > } > > }); > > function B() > { > this.b_construct = 2; > this._super();} > > Object.extend(B, A); > B.prototype.methods({ > test : function() > { > this.b_test = 2; > this._super(); > } > > }); > > function C() > { > this.c_construct = 3; > this._super();} > > Object.extend(C, B); > C.prototype.methods({ > test : function() > { > this.c_test = 3; > this._super(); > } > > }); > > var o = new C(); > window.alert(o.a_construct); //1 > window.alert(o.b_construct); //2 > window.alert(o.c_construct); //3 > o.test(); > window.alert(o.a_test); //1 > window.alert(o.b_test); //2 > window.alert(o.c_test); //3 > > Inherit from Base.prototype and you can use syntactic sugar > `this._super()'. I like much more my previous version with, `name' > argument, but that examples is for someone who want syntactic sugar in > way discussed here. > Regards. Yep, that's sort of I was talking about (implementations of this can be different though, but the main idea - is this one). Good implementation. Some additions bellow: * Regarding to `_super()', it's useful to return the result of the super method call (maybe it will be needed for some reason); * For do not describe constructor function a methods separately, wrapper (builder) can be easily used; * Also, regarding to `name' argument for the `_super()', nothing prevents to make it - if argument is - use it, else - use the same method of the parent prototype. But have to repeat, that all this more just for academical theoretical interest (as `caller' is deprecated and will throw an exception in strict of ES5; by the way, I believe that appearing of the "strict" feature in any technology - is not a good news and mistake of ideology of a language - and that's not about strict itself, that's about dividing on "strict" and "non-strict" which (be sure) will cause many holy-wars and so on, so "strict-feature" can be treated from some viewpoint as a language mistake). Regarding to wrappers (the code I showed above) - it can be used with some assumptions. From the abstraction viewpoint, using of `this._super ()' which is not related to any name, is really more elegant than that long and repeating all names `CurrectConstructor.superclass.prototype.thatMethod.apply(this, arguments)'. This pattern is known also, so some can choose it. /ds
From: Thomas 'PointedEars' Lahn on 15 Jan 2010 12:36 John G Harris wrote: > Thomas 'PointedEars' Lahn wrote: >> John G Harris wrote: >>> I don't see a good case for having [a constructor] property anyway. An >>> object surely knows how to do its own job. If it doesn't then something >>> has gone wrong with OO. >> >> IBTD. A user-defined `constructor' property of the prototype of an >> object can be most useful. One basic principle of OOP is polymorphism, >> and one method of achieving that is overloading; that is, a method is >> defined on an object that is also defined on a superordinate object (in >> class-based OOP: the superclass; in prototype-based OOP: the next object >> in the prototype chain). > > In other languages there is Overloading and there is Overriding. > Although there is no well established terminology for javascript I think > that Overriding is more appropriate here. [...] Thanks. You are correct; overriding is what I meant here. Apologies if my bad choice of words caused confusion. >> Having the `constructor' property of the prototype of an instance allows >> to overload a method in the instance's prototype (or the instance >> itself) and still call the overloaded method as the Function object that >> is the constructor can have (can be added) a user-defined property that >> refers to the constructor of the prototype object that is next in the >> prototype chain. This allows for code re-use, such as common property >> initialization (and is thus most useful in constructors themselves). > > So you have two cases. > Case 1 > x.f > x.constructor.prototype.f > when they are different functions, and > > Case 2 > x.f > x.constructor.base_constructor.prototype.f > which gets you the immediate less-derived function, if it exists. > > I'd have thought that Case 1 is fairly rare, as the usual arrangement is > for instances to hold most of the data properties and prototype objects > to hold all of the function properties. > > For both cases wouldn't it be cleaner to write > x.protoT.f > x.base_protoT.f > It's less typing and nothing bad happens if constructor.prototype is > reassigned. There is no built-in way to access the second-next aso. object in the prototype chain directly, and as you do not want to augment the object with a fitting property when constructing it, that leaves the prototype object associated with the constructor (which can be filtered with Object.prototype.hasOwnProperty() or an iterator method) or the constructor itself (which is not in the prototype chain of the object and so does not need to be considered when iterating) as owner of the property. >> It also allows for an object to refer to its constructor without >> explicitly using the constructor's identifier, which makes code re-use >> and maintenance easier. > > Copy and paste reuse maybe, but I'm not so sure about maintenance. Then ask yourself why so many other programming languages have a `super' keyword (or the like), why that very keyword is a future reserved word in ECMAScript Eds. 3/5, and why it is implemented in JScript .NET as specified in Netscape's ECMAScript Ed. 4 draft. Apparently there is a need to refer to the superordinate object despite built-in inheritance. In a constructor this pattern is most useful because you can initialize instance properties (not inherited) in the constructor associated with the (prototype) object in the prototype chain. It allows calling the superordinate constructor to initialize those properties without having to keep track of API changes. > Explicit constructor names make it obvious what the original coder was > thinking. That requires constant maintenance of objects earlier in the prototype chain should the prototype chain be modified later. >> One should be aware, though, that a user-defined `constructor' property, >> like most user-defined properties, is enumerable. If the user-defined >> object should be subject to for-in iteration, it appears necessary that >> it provides an iterator that ignores those properties and other user >> defined properties that should not show up in the loop. > > I thought using hasOwnProperty is normal practice there. If you consider that there are implementations where Object.prototype.hasOwnProperty() is not available, it becomes safer and more efficient to use an iterator method. Because you would need to emulate hasOwnProperty() then (which means almost the same penalty as with the iterator) and you could not assume that the implementation provides means to detect reliably whether a property was inherited or not. PointedEars -- var bugRiddenCrashPronePieceOfJunk = ( navigator.userAgent.indexOf('MSIE 5') != -1 && navigator.userAgent.indexOf('Mac') != -1 ) // Plone, register_function.js:16
From: John G Harris on 15 Jan 2010 15:27 On Fri, 15 Jan 2010 at 18:36:57, in comp.lang.javascript, Thomas 'PointedEars' Lahn wrote: >John G Harris wrote: <snip> >>> It also allows for an object to refer to its constructor without >>> explicitly using the constructor's identifier, which makes code re-use >>> and maintenance easier. >> >> Copy and paste reuse maybe, but I'm not so sure about maintenance. > >Then ask yourself why so many other programming languages have a `super' >keyword (or the like), why that very keyword is a future reserved word in >ECMAScript Eds. 3/5, and why it is implemented in JScript .NET as specified >in Netscape's ECMAScript Ed. 4 draft. Apparently there is a need to refer >to the superordinate object despite built-in inheritance. As it happens, Java uses 'super' but C++ uses the class name, which can be any of the less-derived classes. I've occasionally seen people ask for 'super' in C++, but never anyone rejecting the class name feature. >In a constructor this pattern is most useful because you can initialize >instance properties (not inherited) in the constructor associated with the >(prototype) object in the prototype chain. You need access to the base constructor but it doesn't have to be by a particular route. Languages that have 'super' usually don't have any other route. Javascript is more flexible. >It allows calling the >superordinate constructor to initialize those properties without having to >keep track of API changes. <snip> You very definitely need to keep track of any parameter changes. John -- John Harris
From: Thomas 'PointedEars' Lahn on 15 Jan 2010 20:19
John G Harris wrote: > Thomas 'PointedEars' Lahn wrote: >> John G Harris wrote: >>>> It also allows for an object to refer to its constructor without >>>> explicitly using the constructor's identifier, which makes code re-use >>>> and maintenance easier. >>> Copy and paste reuse maybe, but I'm not so sure about maintenance. >> >> Then ask yourself why so many other programming languages have a `super' >> keyword (or the like), why that very keyword is a future reserved word >> in ECMAScript Eds. 3/5, and why it is implemented in JScript .NET as >> specified in Netscape's ECMAScript Ed. 4 draft. Apparently there is a >> need to refer to the superordinate object despite built-in inheritance. > > As it happens, Java uses 'super' In other languages you can use the class name as well. > but C++ uses the class name, which can be any of the less-derived > classes. If I am not very much mistaken, you can do that in PHP and Python, too. > I've occasionally seen people ask for 'super' in C++, but never anyone > rejecting the class name feature. That only means that if there is only one way, you have to deal with that. That does not mean this is a Good Thing. >> In a constructor this pattern is most useful because you can initialize >> instance properties (not inherited) in the constructor associated with >> the (prototype) object in the prototype chain. > > You need access to the base constructor but it doesn't have to be by a > particular route. Languages that have 'super' usually don't have any > other route. I am afraid you are mistaken. For example, it can be done in two ways in PHP and Python. > Javascript is more flexible. There is no "Javascript", and non sequitur. Properties can be dynamically added in PHP and Python, for example. >> It allows calling the superordinate constructor to initialize those >> properties without having to keep track of API changes. > > You very definitely need to keep track of any parameter changes. True, but a good API change is one that does not make this a necessity as well. PointedEars -- var bugRiddenCrashPronePieceOfJunk = ( navigator.userAgent.indexOf('MSIE 5') != -1 && navigator.userAgent.indexOf('Mac') != -1 ) // Plone, register_function.js:16 |