From: Asen Bozhilov on
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
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
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
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
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