Super-calls

# Axel Rauschmayer (14 years ago)

just trying to understand: how is super different from proto?

Another way to explain super-calls:

Given a chain of prototypes: this -> O1 => O2 => O3

Then a super-call is always about letting "this" stay the same, but finding a "later" method: If your method lives in O1, you start your search for the super-property after O1 etc. In code this looks as follows: here.proto.foo.call(this, …) where "here" means "the object that the current method lives in". The effect is then:

  • here.proto: start your search after the method’s object and look for "foo".
  • .call(this, …): but keep "this" the same.

"this" must be the same, because the properties usually reside in O1 and every method must be able to access those. In other words: Even though you invoke a different method, the compound object starting at O1 must be the same.

Two variations that don’t work:

  1. this.proto.foo.call(this, …)
  2. this.proto.foo(…)

.#1 does not work, because it will always start its search in O2 (the proto of "this") and not in the object after the method’s object (as it should).

.#2 does not work, because it will result in "this" being O2 in foo(). Thus, we have just lost our properties and cannot change the state of the (compound) object, any more.

# Lasse Reichstein (14 years ago)

On Sat, Oct 1, 2011 at 2:16 PM, Axel Rauschmayer <axel at rauschma.de> wrote:

Then a super-call is always about letting "this" stay the same, but finding a "later" method: If your method lives in O1, you start your search for the super-property after O1 etc. In code this looks as follows: here.proto.foo.call(this, …) where "here" means "the object that the current method lives in". The effect is then:

  • here.proto: start your search after the method’s object and look for "foo".
  • .call(this, …): but keep "this" the same.

Am I right that super-calls only works for class methods, because they know the, statically determinable, prototype chain of its instances, and therefore it knows where to start the search.

A normal method, e.g., var o = {proto: { m: function(x) { alert(x); }}; o.m = function(v) { super(v); }; // doesn't work o.m("hello"); won't be able to use "super", because it doesn't know where to start the search - all it knows is the this-argument to the call and the function itself, which doesn't necessarily mean anything.

# Brendan Eich (14 years ago)

On Oct 1, 2011, at 4:23 PM, Lasse Reichstein wrote:

On Sat, Oct 1, 2011 at 2:16 PM, Axel Rauschmayer <axel at rauschma.de> wrote: Then a super-call is always about letting "this" stay the same, but finding a "later" method: If your method lives in O1, you start your search for the super-property after O1 etc. In code this looks as follows: here.proto.foo.call(this, …) where "here" means "the object that the current method lives in". The effect is then:

  • here.proto: start your search after the method’s object and look for "foo".
  • .call(this, …): but keep "this" the same.

Am I right that super-calls only works for class methods, because they know the, statically determinable, prototype chain of its instances, and therefore it knows where to start the search.

A normal method, e.g., var o = {proto: { m: function(x) { alert(x); }}; o.m = function(v) { super(v); }; // doesn't work

You'd write super.m(v) there. See harmony:object_initialiser_super

# Axel Rauschmayer (14 years ago)

Am I right that super-calls only works for class methods, because they know the, statically determinable, prototype chain of its instances, and therefore it knows where to start the search.

Yes that’s a tricky problem. There are two solutions:

  1. Keep a dynamic variable "here" (similar to "this") that is filled in when invoking the method. You have to traverse the prototype chain to find the method and thus know which object it is in. Advantage: robust with regard to dynamic changes to properties. Disadvantage: high cost, even for methods that don’t use "super" (and it won’t be that frequently used a feature).

  2. Statically store in methods what object they come from. This works best with object literals. Consult [1] for the details – it’s an internal property called [[Super]]. In theory, one could also have a property [[Here]], to support accessing sibling properties, but with modules, I don’t think that is a frequent use case. If one uses an object literal for modularity, one has to be careful not to use "this" to access siblings.

[1] harmony:object_initialiser_super

# John J Barton (14 years ago)

On Sat, Oct 1, 2011 at 8:22 AM, Brendan Eich <brendan at mozilla.com> wrote:

On Oct 1, 2011, at 4:23 PM, Lasse Reichstein wrote:

On Sat, Oct 1, 2011 at 2:16 PM, Axel Rauschmayer <axel at rauschma.de> wrote:

Then a super-call is always about letting "this" stay the same, but finding a "later" method: If your method lives in O1, you start your

search

for the super-property after O1 etc. In code this looks as follows: here.proto.foo.call(this, …) where "here" means "the object that the current method lives in". The effect is then:

  • here.proto: start your search after the method’s object and look for "foo".
  • .call(this, …): but keep "this" the same.

Am I right that super-calls only works for class methods, because they

know

the, statically determinable, prototype chain of its instances, and therefore it knows where to start the search. A normal method, e.g., var o = {proto: { m: function(x) { alert(x); }}; o.m = function(v) { super(v); }; // doesn't work

You'd write super.m(v) there. See

harmony:object_initialiser_super

The idea sounds interesting but unfortunately reference is written in a language I don't understand. How about this case:

var widget = { hookup: function() { // |this| is widget // |super| is widget window.addEventListener('load', function(event) { // |this| is NOT widget // |super| ?? }, false); } }; widget.hookup();

jjb

# Axel Rauschmayer (14 years ago)

Example: function SuperClass() { }

function SubClass() {
}
SubClass.prototype = Object.create(SuperClass);
SubClass.prototype.foo = function() {
    super.foo();
};

Behind the scenes:

  • SubClass.prototype.foo.[[Super]] = SuperClass.prototype;

  • foo is desugared to:

    SubClass.prototype.foo = function thisFunction() { // named function expression thisFunction.[[Super]].foo.call(this); };

The “behind the scenes” work would be performed for object literals with a proto operator and for class literals.

# François REMY (14 years ago)

In my understanding, super would be null.

What would be more complex is : var widget = { hookup: function() { // |this| is widget // |super| is widget window.addEventListener('load', function(event) { // |this| is widget // |super| ?? }.bind(this), false); } }; widget.hookup(); We have got a problem here because there’s no way to “keep” super working in an asynchronous pattern. Well, you still can perform “var Super = super; .... { ... Super.foo(); ... } ...”

From: John J Barton Sent: Saturday, October 01, 2011 5:51 PM To: Brendan Eich Cc: Axel Rauschmayer ; es-discuss Subject: Re: Super-calls

On Sat, Oct 1, 2011 at 8:22 AM, Brendan Eich <brendan at mozilla.com> wrote:

On Oct 1, 2011, at 4:23 PM, Lasse Reichstein wrote:

On Sat, Oct 1, 2011 at 2:16 PM, Axel Rauschmayer <axel at rauschma.de> wrote:

Then a super-call is always about letting "this" stay the same, but finding a "later" method: If your method lives in O1, you start your search for the super-property after O1 etc. In code this looks as follows: here.proto.foo.call(this, …) where "here" means "the object that the current method lives in". The effect is then:

  • here.proto: start your search after the method’s object and look for "foo".
  • .call(this, …): but keep "this" the same.

Am I right that super-calls only works for class methods, because they know the, statically determinable, prototype chain of its instances, and therefore it knows where to start the search. A normal method, e.g., var o = {proto: { m: function(x) { alert(x); }}; o.m = function(v) { super(v); }; // doesn't work

You'd write super.m(v) there. See harmony:object_initialiser_super

The idea sounds interesting but unfortunately reference is written in a language I don't understand. How about this case:

var widget = { hookup: function() { // |this| is widget // |super| is widget window.addEventListener('load', function(event) { // |this| is NOT widget // |super| ?? }, false); } }; widget.hookup();

jjb

# Axel Rauschmayer (14 years ago)

Small corrections...

Example: function SuperClass() { }

function SubClass() {
}
SubClass.prototype = Object.create(SuperClass.prototype);
SubClass.prototype.foo = function() {
    super.foo();
};

Behind the scenes:

  • SubClass.prototype.foo.[[Super]] = Object.getPrototypeOf(SubClass.prototype);

  • foo is desugared to:

    SubClass.prototype.foo = function thisFunction() { // named function expression thisFunction.[[Super]].foo.call(this); };

The “behind the scenes” work would be performed for object literals with a proto operator and for class literals.

# John J Barton (14 years ago)

On Sat, Oct 1, 2011 at 9:05 AM, François REMY <fremycompany_pub at yahoo.fr>wrote:

In my understanding, super would be null.

What would be more complex is :

var widget = { hookup: function() { // |this| is widget // |super| is widget window.addEventListener('load', function(event) { // |this| is widget // |super| ?? }.bind(this), false);

Unfortunately my example and your fix are both impractical. We have to bind

the function and save a reference to it because we don't have garbage collection. That provides another example to try to understand super: this.loadHandler = function(event){ // this is widget // Now super? }.bind(this); window.addEventListener('load', this.loadHandler, false);

# François REMY (14 years ago)

My code was not a fix, it was intended to show that while your first case’ behavior was explained in the spec (super had to be null), the one of my own case was not (ie: the interaction of ‘super’ with bind).

I’ve no idea of how we should solve the problem. Maybe the ‘bind’ method should create a copy of the original function whose ‘boundThis’ is equal to the object’s this and whose ‘super’ is equal to Object.getPrototypeOf(this).

function Obj() { } Obj.prototype.getX = function() { return 10; }

function Obj2() { Obj(this); } Obj2.prototype = Object.create(Obj.prototype); Obj2.prototype.getX = function() { return super.getX()+1; }

var a = new Obj2(); var b = Object.create({getX:function() { return 100; }}); b.getX=a.getX.bind(b);

assert(a.getX() == 11); assert(a.getX() == 101); // or should it be 11? A typical programming language would (probably) require 11, but then you’ve no way to solve the asynchronous pattern (super would remain null and only this would be bound).

François

From: John J Barton Sent: Saturday, October 01, 2011 6:16 PM To: François REMY Cc: Brendan Eich ; Axel Rauschmayer ; es-discuss Subject: Re: Super-calls

On Sat, Oct 1, 2011 at 9:05 AM, François REMY <fremycompany_pub at yahoo.fr> wrote:

In my understanding, super would be null.

What would be more complex is : var widget = { hookup: function() { // |this| is widget // |super| is widget window.addEventListener('load', function(event) {

            // |this| is widget
            // |super| ??
        }.bind(this), false);

Unfortunately my example and your fix are both impractical. We have to bind the function and save a reference to it because we don't have garbage collection. That provides another example to try to understand super: this.loadHandler = function(event){ // this is widget // Now super? }.bind(this); window.addEventListener('load', this.loadHandler, false);

    }
};
widget.hookup();

jjb

# Axel Rauschmayer (14 years ago)

On Oct 2, 2011, at 1:55 , Lasse Reichstein wrote:

On Sat, Oct 1, 2011 at 5:36 PM, Axel Rauschmayer <axel at rauschma.de> wrote:

Am I right that super-calls only works for class methods, because they know the, statically determinable, prototype chain of its instances, and therefore it knows where to start the search.

Yes that’s a tricky problem. There are two solutions:

  1. Keep a dynamic variable "here" (similar to "this") that is filled in when invoking the method. You have to traverse the prototype chain to find the method and thus know which object it is in. Advantage: robust with regard to dynamic changes to properties. Disadvantage: high cost, even for methods that don’t use "super" (and it won’t be that frequently used a feature).

That's the solution I could see, if it is going to work dynamically.

  1. Statically store in methods what object they come from. This works best with object literals. Consult [1] for the details – it’s an internal property called [[Super]]. In theory, one could also have a property [[Here]], to support accessing sibling properties, but with modules, I don’t think that is a frequent use case. If one uses an object literal for modularity, one has to be careful not to use "this" to access siblings.

That sounds like it would trip up reusing functions across different objects. If I define a function outside of any object, and then assign it to two different functions' prototypes, it's not a property of the function what "super" should refer to - if it should work in any predictable way.

I'm not too fond of implicitly or automatically binding functions.

It’s a performance thing support for dynamic "super" would slow everything down and is thus not worth it. In the current spec, there is a method for moving methods with "super" from one object to another. It’s not as elegant, but given the performance cost of dynamic "super", it’s the right call.

Details in this thread: esdiscuss/2011-June/015334

Axel

# Erik Arvidsson (14 years ago)

On Mon, Oct 3, 2011 at 14:50, Axel Rauschmayer <axel at rauschma.de> wrote:

It’s a performance thing support for dynamic "super" would slow everything down and is thus not worth it. In the current spec, there is a method for moving methods with "super" from one object to another. It’s not as elegant, but given the performance cost of dynamic "super", it’s the right call.

I'm not sure it is just a performance issue. I believe the semantics is wrong too.

class B { a() { this.b(); } b() { print('B.b'); } }

class C extends B { a() { super.a(); } b() { print('C.b'); } }

var c = new C; c.a(); // Should print 'C.b'

With a dynamic super the above would lookup b in the wrong object (B.prototype instead of C.prototype).

# Quildreen Motta (14 years ago)

On 03/10/11 19:49, Erik Arvidsson wrote:

On Mon, Oct 3, 2011 at 14:50, Axel Rauschmayer<axel at rauschma.de> wrote:

It’s a performance thing support for dynamic "super" would slow everything down and is thus not worth it. In the current spec, there is a method for moving methods with "super" from one object to another. It’s not as elegant, but given the performance cost of dynamic "super", it’s the right call. I'm not sure it is just a performance issue. I believe the semantics is wrong too.

class B { a() { this.b(); } b() { print('B.b'); } }

class C extends B { a() { super.a(); } b() { print('C.b'); } }

var c = new C; c.a(); // Should print 'C.b'

With a dynamic super the above would lookup b in the wrong object (B.prototype instead of C.prototype)

As I understand, dynamic super is different from dynamic this.

With dynamic super, you'd still get C.b' in that call, because thethisObject' from the a function remains the same, super only changes the object in which the method is looked upon.

So, a desugared (and wrong, I reckon, but bear with me for awhile) way of writing that would be:

var C = { a: function() { B.a.call(this) } b: function() { print('C.b') }}

var c = Object.create(C) c.a() // 'C.b'

The problem with that explicit B' is that a function doesn't really belong to an object in JS, it might be assigned to anything, and it's expect that it'll work all the same. So, the engine would need a way of tracking what the next object in the prototype chain is for *looking up* the method to use. Once it finds that method, it applies the method to the currentthisObject'.

The problem then, with dynamic super, becomes that one needs to pass the called method a hint of what the next object in the prototype chain is, since we can't use this' — it'll always be the same in all methods called throughsuper'.

Static super solves that problem by placing that information directly in the method, so it's just a lookup away. Dynamic super solves that problem by passing the information as an implicit parameter to every function call, just like `this', thus being a perf problem.

I think it boils down to a performance vs semantics problem in the end. I personally think the semantics dynamic super provides fit better with a prototypical and overly dynamic language, as JavaScript is (at least ES5 is).

# Axel Rauschmayer (14 years ago)

class B { a() { this.b(); } b() { print('B.b'); } }

class C extends B { a() { super.a(); } b() { print('C.b'); } }

var c = new C; c.a(); // Should print 'C.b'

With a dynamic super the above would lookup b in the wrong object (B.prototype instead of C.prototype).

Note that with dynamic super, "this" never changes during the following method invocations, only "here" changes.

c.a() => this = c, here = C.prototype (where a() was found)

super.a() => this = c, here = B.prototype. Explanation for "here": a() was found by searching the prototype chain, starting at the prototype of the previous "here". Thus, the search starts at B.prototype where a property "a" is found.

this.b() => this = c. The search for b() starts at "this" = c and finds a property "b" in the prototype of c (which is C.prototype).

So it should work. It’s actually closer to the intuitive meaning of "super.a":

  • Perform the invocation as if it was this.a (meaning that the value of "this" is unchanged).
  • But: start the search for "a" in the prototype of the object where the current method "lives" (the "here" variable mentioned above).

super.a(arg1, arg2) => Object.getPrototypeOf(here).a.call(this, arg1, arg2)

# Axel Rauschmayer (14 years ago)

From: Quildreen Motta <quildreen at gmail.com> Subject: Re: Super-calls Date: October 4, 2011 1:19:33 GMT+02:00 To: es-discuss at mozilla.org

On 03/10/11 19:49, Erik Arvidsson wrote:

On Mon, Oct 3, 2011 at 14:50, Axel Rauschmayer<axel at rauschma.de> wrote:

It’s a performance thing support for dynamic "super" would slow everything down and is thus not worth it. In the current spec, there is a method for moving methods with "super" from one object to another. It’s not as elegant, but given the performance cost of dynamic "super", it’s the right call. I'm not sure it is just a performance issue. I believe the semantics is wrong too.

class B { a() { this.b(); } b() { print('B.b'); } }

class C extends B { a() { super.a(); } b() { print('C.b'); } }

var c = new C; c.a(); // Should print 'C.b'

With a dynamic super the above would lookup b in the wrong object (B.prototype instead of C.prototype)

The problem then, with dynamic super, becomes that one needs to pass the called method a hint of what the next object in the prototype chain is, since we can't use this' — it'll always be the same in all methods called throughsuper'.

Static super solves that problem by placing that information directly in the method, so it's just a lookup away. Dynamic super solves that problem by passing the information as an implicit parameter to every function call, just like `this', thus being a perf problem.

Correct, with a dynamic super, you keep track of "here" while doing the method lookup, with static super, you hardcode (which is fine, unless you move the method).

Thus, statically, the code above is rewritten as follows:

class B { a() { this.b(); } b() { print('B.b'); } }

class C extends B { a: function func() { // C.prototype.a.[[Super]] = B.prototype (assigned statically) func.[[Super]].a.call(this); }, b() { print('C.b'); } }

super being rare and moving methods being rarer, I think the tradeoff for performance is OK, especially as there will be a method that allows you to move methods. If performance wasn’t an issue, dynamic "super" would be preferable.

# Quildreen Motta (14 years ago)

On 03/10/11 20:44, Axel Rauschmayer wrote:

super being rare and moving methods being rarer, I think the tradeoff for performance is OK, especially as there will be a method that allows you to move methods. If performance wasn’t an issue, dynamic "super" would be preferable.

Hm, I wouldn't consider moving methods to be that rare, unless you're taking into account only people coding in a declarative style. In that case, moving a method would be a weird thing to do. On the other hand, if you're writing imperative prototypical code, moving methods might not be such a rare thing — more so if we take into account the lack of multiple-inheritance facilities in JS, which would lead someone to use things like mixins (thus, more overhead due to manual copying, but mixins are — or should be — parentless anyways).

Note, though, that this is based only on my own code. I am not much knowledgeable about the general use-case of JavaScript, so feel free to correct me where I'm rambling non-senses :3

Another point is what "here" should refer to in a situation like:


var oddball = { clone: function() { this.instances = (+this.instances || 0) + 1 return this } , describe: function() { return this.name + ' has ' + this.instances + ' copies' }}

var object = oddball <| { describe: function() { return '<#object ' + super.describe() + '>' }}

var me = object.clone() me.name = 'Me'

var another = { describe: function() { return 'The princess is in another castle.' }}

me.describe() // => '<#object Me has 1 copies>'

object.describe.call(Object.create(another)) // => '<#object undefined has undefined copies>'

In this case, should here' take into account the object in which the actiondescribe' is defined, in this case resolving to oddball.describe', or should it take into account the object that was the target of the action, in this case resolving toanother.describe'.

My opinion is that the latter makes more sense, but that's because I see `thisObject' not just as a data-container, but something that describes the full behaviours of a thing.

# Allen Wirfs-Brock (14 years ago)

On Oct 1, 2011, at 11:11 AM, François REMY wrote:

My code was not a fix, it was intended to show that while your first case’ behavior was explained in the spec (super had to be null), the one of my own case was not (ie: the interaction of ‘super’ with bind).

All well defined in the proposal

Remember the |super| can be thought of as having two values depending upon the usage. When evaluated for value, it value is always the same as the this value. In a bound function the, evaluated value of super is the bound this value. The other value of super is the property lookup continuation value. That value is statically bound when the function is created (ie, installed as a method in an object). It is the value of the object's [[Prototype]] internal property.

var widget = { hookup: function() { // |this| is widget >>>>>> actually depend upon how function is invoked, normal yes normally widget // |super| is widget >>>>>> no, and not null. For evaluation purposes it is the same as |this| >>>>>> the lookup continuation is Object.prototype which is the [[Prototype]] of the containing obj lit window.addEventListener('load', function(event) { // |this| is widget // |super| ?? >>>>>> for evaluation purposes it is widget (as bound by bind) >>> >>>>>> the lookup continuation is null, because it doesn't meet the "part of an object literal" criterial below :

from proposal: "When a function that references super is defined as part of an object literal its [[Super]] internal property is set to the same value as the [Prototype]] internal property of the object created by the object literal. Such functions include functions defined using method property definitions, functions defined using get or set definitions, and functions defined as a MemberExpression within the AssignmentExpression of a PropertyAssignment. Functions defined outside of object literals (or class declarations) that reference super are created with their [[Super]] internal property set to null. Property accesses based off of super always perform property lookups start with the object that is the the value of the containing function’s [[Super]] internal property. If [[Super]] is null, the property lookup immediately fails and produces the value undefined." }.bind(this), false);

Expressing this criteria another way, a function in an object literal only gets a non-null [[Super]] value if the function is either the immediate value of an data property or the [[Get]] or [[Set]] function of an accessor property.

I’ve no idea of how we should solve the problem. Maybe the ‘bind’ method should create a copy of the original function whose ‘boundThis’ is equal to the object’s this and whose ‘super’ is equal to Object.getPrototypeOf(this).

Object.defineMethod is used to rebind [[Super]] (actually creates a new function with the same code and [[Scope]] but a different [[Super]] binding).

defineMethod and bind have nothing to do with each other. bind is about the value of |this| which is always the same as the value of |super|. defineMethod is about the the value of [[Super]] - the property lookup continuation point.

function Obj() { } Obj.prototype.getX = function() { return 10; }

function Obj2() { Obj(this); } Obj2.prototype = Object.create(Obj.prototype); Obj2.prototype.getX = function() { return super.getX()+1; } [[Super]] of getX would be null. You probably want to say: Object.defineMethod( Obj2.prototype, 'getX', function () {return super.getX() + 1}; in which case [[Super]] of getX would be Obj.prototype

var a = new Obj2(); var b = Object.create({getX:function() { return 100; }}); b.getX=a.getX.bind(b);

I suspect what you really want to say above is Object.defineMethod(b, 'getX', a.getX).bind(b);

assert(a.getX() == 11);

yes 11 is correct

assert(a.getX() == 101); // or should it be 11?

false. Or did you mean assert (b.getX() == 101)

as written above, g.getX) will also be 11. this is because of the static binding of [[Super]] when the method is installed

A typical programming language would (probably) require 11,

I know of no other programming language that permits something like bind to permanently fix a methods this bind or that permits a method (that references this) to be invoked without supply explicitly supplying a this value.

but then you’ve no way to solve the asynchronous pattern (super would remain null and only this would be bound).

This whole business of trying to bind this in a callback is a idiom that I think is unique to JS. In any other language, the problem would solved by using a lambda to capture whatever state the callback function need to reference:

...
{ //lexical block
    let  actualWidget = this;
    window.addEventListener('load', function (event) {
          actualWidget.whatever();  //instead of this.whatEver
   }, false);
};

...

binding this for non-method function invocations should be considered a JS antipattern.

# Axel Rauschmayer (14 years ago)

So you are asking how "super" works with generic methods? Good question.

Statically, things are easy: super.describe() at (*) will always invoke oddball.describe()

Dynamically, things are tricky. call() would have to use the "here" of object.describe which is object. Thus, super.describe() would find oddball.describe and give it a "this" === Object.create(another).

I’m not sure "super" makes much sense in generic methods, because those stand largely on their own.

# Allen Wirfs-Brock (14 years ago)

On Oct 3, 2011, at 5:15 PM, Quildreen Motta wrote:

On 03/10/11 20:44, Axel Rauschmayer wrote:

super being rare and moving methods being rarer, I think the tradeoff for performance is OK, especially as there will be a method that allows you to move methods. If performance wasn’t an issue, dynamic "super" would be preferable.

Axel has this exactly right. Ideally, a super property lookup would be a dynamic continuation of the property lookup. However, enabling such a dynamic lookup continuation imposes what is generally considered to be an unacceptable tax on every function invocation. Having a method statically capture its lookup continuation point is a slightly less flexible solution but it eliminates the every call tax. Every object-oriented language that I'm familiar with define the semantics of super using this static binding semantics.

Calling a function that does a super lookup using direct invocation rather than via a method invocation is inherently bogus. super.foo means lookup foo starting at the continuation point of the lookup that retrieved the currently executing method. If there was no such lookup to continue, super.foo has no "correct" semantics because. Don't do it! In fact the static [[Super]] binding semantics does specify what will happen. But if a programmer intentionally coded this in a function that is expected to be called via direct invocation then they have a design bug.

Hm, I wouldn't consider moving methods to be that rare, unless you're taking into account only people coding in a declarative style. In that case, moving a method would be a weird thing to do. On the other hand, if you're writing imperative prototypical code, moving methods might not be such a rare thing — more so if we take into account the lack of multiple-inheritance facilities in JS, which would lead someone to use things like mixins (thus, more overhead due to manual copying, but mixins are — or should be — parentless anyways).

The think to remember is to use Object.defineMethod anytime you want copy a method from one object to another. Even this the method doesn't contain a super refer. (Who knows, it might tomorrow).