I noticed that the Function.prototype
has a toMethod()
method in experimental JavaScript, but what does that actually do? And how do I use it?

- 18,808
- 10
- 90
- 132

- 1,511
- 9
- 18
-
1Perhaps related: https://esdiscuss.org/topic/any-tomethod-use-case#content-1 – Derek 朕會功夫 Dec 16 '14 at 18:45
-
I've never done any mixins or class compositions when it comes to inheritance. so I still don't understand what they are talking about or how to use it – Edwin Reynoso Dec 16 '14 at 18:52
-
1@Edwin - I don't think it's meant for use by the casual JavaScript developer. It's a very deep level function for use in advanced JavaScript libraries which depend on some features of prototype inheritance that are also in "experimental" status (like the "`super()`" function) – JDB Dec 16 '14 at 18:59
-
From [another source](https://cure53.de/es6-for-penetration-testers.pdf): "The purpose of Function.toMethod() is to provide means for accessing a method from a superclass and generating a fresh function object with a new home." – Derek 朕會功夫 Dec 16 '14 at 18:59
-
Ok can someone write a quick script that uses two classes one that extends from another one and using the **.toMethod()** because when I called **.toMethod** on a function it returned a new function yet I'm not sure what changed. Like in **.bind** the context changes – Edwin Reynoso Dec 16 '14 at 19:02
2 Answers
Update: the toMethod
method was experimental only and did not make it into the standard. The home object is essentially static now, the only way to manipulate super
is to change the [[prototype]]:
var base = {…}; // as below
var obj = Object.setPrototypeOf({
foo() { // needs to use method definition syntax
super.foo();
}
}, base);
obj.foo();
It's very similar to the bind
method of function objects. However, instead of creating a new function with a bound this
value, it creates a new function with a bound [[HomeObject]]
, which is the reference that is used for super
calls:
[[HomeObject]]
(Object): If the function usessuper
, this is the object whose[[GetPrototypeOf]]
provides the object where super property lookups begin.
Consider this example (not using any class syntax):
var base = {
foo: function() {
console.log("base foo called on", this);
}
};
base.foo(); // base foo called on base
var obj = Object.create(base);
obj.foo(); // base foo called on obj
obj.foo = function() {
super.foo();
};
obj.foo(); // ReferenceError: this method has no home
obj.bar = obj.foo.toMethod(obj);
obj.bar(); // base foo called on obj
obj.baz = function() {
super();
};
obj.baz(); // ReferenceError: this constructor has no parent class
Reflect.setPrototypeOf(obj.baz, base.foo);
obj.baz(); // base foo called on obj

- 630,263
- 148
- 957
- 1,375
-
I understand how to use bind and that it returns a new function with a different context but the **[[HomeObject]]** that I don't understand – Edwin Reynoso Dec 16 '14 at 18:58
-
-
I'm not familiar with how this all works, but it seems like it should be `obj.bar = obj.foo.toMethod(base);`, right? Aren't you setting the `[[HomeObject]]` to `base`? – JDB Dec 16 '14 at 20:38
-
@JDB: No, I'm setting the `[[HomeObject]]` to `obj`, because `super` basically means `GetPrototypeOf([[HomeObject]])` – Bergi Dec 16 '14 at 20:40
-
Ah... so to get foo to work without a reference error, you'd use `obj.foo = (function(){super.foo()}).toMethod(obj);` Or would that cause an infinite loop? – JDB Dec 16 '14 at 20:45
-
No, I think that's exactly what needs to be done (and how `obj.bar` is defined in my example) – Bergi Dec 16 '14 at 20:50
-
@Bergi was `.toMethod` deprecated? I can't seem to find it implemented in any browser. – nils May 12 '16 at 06:39
-
@nils: Yes, it's been removed from ES6 and deferred to later revisions (if at all). It seems Chrome did implement it once. – Bergi May 12 '16 at 11:14
-
The lack of `toMethod` combined with static `super` makes it really difficult to copy a method from one class to another. – trusktr Jul 26 '16 at 06:23
-
@trusktr: Yeah, it's the lack of `toMethod` that makes `super` static in the first place :-) – Bergi Jul 26 '16 at 12:53
-
@Bergi is there a way to still implement this example? now it threw error: unexpected super. it seems like the example is not a method definition thus super can't be used inside – whales Dec 21 '16 at 04:37
-
@whales hardly, see the update. You're correct, `super` outside of method definitions is a syntax error now. – Bergi Dec 21 '16 at 04:52
-
@jinbeomhong No, `Reflect` does not provide a workaround. What are you trying to do? – Bergi Jul 15 '19 at 19:19
My understanding is that .toMethod
is like cloning a function. Consider the example in the source I posted,
class P { }
class C extends P {
foo() {
console.log("f");
super();
}
}
P.prototype.foo=C.prototype.foo;
(new C).foo();
Here you reference a subclass method .foo
in the superclass, so when you call .foo
, it will reference P
's .foo
which is C
's .foo
and you have just created a loop.
It seems like to solve this issue, you can use .toMethod
which "clones" the function and give it a different super
/"home" that you specifed:
P.prototype.foo = C.prototype.foo.toMethod(P.prototype);
now calling (new C).foo()
would not go on forever.

- 92,235
- 44
- 185
- 247
-
ok there's only one thing I don't understand and then I'll get it. Is the **super()** representing the **class P** – Edwin Reynoso Dec 16 '14 at 19:16
-
I think now the method is belong to P so `super` would be not available at all. – Derek 朕會功夫 Dec 16 '14 at 19:25
-
before calling **.toMethod** is this the same in es5: `function P(){}` `function C(){}` `C.prototype = new P();` `C.prototype.foo = function(){ console.log('f'); P(); }` `P.prototype.foo = C.prototype.foo;` `(new C).foo()` – Edwin Reynoso Dec 16 '14 at 19:27
-
I've now studied the draft for half an hour, and came to the conclusion that you'd need to do `super.foo()` instead of just `super()` - which would only work for (constructor) functions that inherit from other functions. Can anyone confirm (test?) this? – Bergi Dec 16 '14 at 19:32
-
@Bergi - I have been thinking about that too, since super is just the constructor. – Derek 朕會功夫 Dec 16 '14 at 19:35
-
1@Bergi: I know this is old and you probably know the answer by know, but just for reference: AFAIK `super()` *used* to be valid in every method and it would just call the parent method. But the spec changed recently and `super()` is now only allowed in the constructor `super.method()` is indeed the way to call parent methods in overridden methods. – Felix Kling Jan 14 '15 at 01:58
-
@Bergi: Oh :D I think I read that thread but didn't realize or remember that you asked. NVM then :) (I just stumbled upon this question while browsering the ecmascrip-6 tag). – Felix Kling Jan 14 '15 at 02:41