Instance bound class methods

# Matthew Robb (9 years ago)

Are there any proposals or any discussions around solving the problem of instance bound class methods with some sugar?

There are examples of people doing things like this: reactjs/react-future/blob/master/01 - Core/01 - Classes.js#L31

My proposal would be to extend method shorthand syntax to support the arrow:

class A extends React.Component {
  handleClick(event)=> {
     ...
  }
}

Which would be sugar for:

class A extends React.Component {
  handleClick = (event)=> {
     ...
  }
}
  • Matthew Robb
# Bucaran (9 years ago)

This and arrow generators would be a nice thing to have.

# Brendan Eich (9 years ago)

You're counting on the property assignment being moved into the constructor, where this is bound. In a class body in ES6 (without property assignment extension), especially in the top level where method defintiions go, this isn't obviously bound to the newly constructed instance.

Ok, that's kind of a nit, or an observation. No worries.

Bigger question is what we want: method per instance allocation cost, which what you did imposes? Or something that can be more efficiently implemented, such as what Strong/SoundScript proposes (last I looked). The latter is what Java and C++ do. Then the trick is enabling first-class function extraction from method, which is a pay-for-what-you-ask-for alternative to allocation per method per constructed instance.

# Bradley Meck (9 years ago)

I am curious if zenparsing/es-function-bind would be related, since it would allow bound function calls to be made by using obj::fn while obj.fn would result in the unbound first class function.

# Kevin Smith (9 years ago)

I am curious if zenparsing/es-function-bind would be related, since it would allow bound function calls to be made by using obj::fn while obj.fn would result in the unbound first class function.

Well, for that syntax proposal, it would be ::obj.fn.

But see zenparsing/es-function-bind#17 for some interesting semantic issues around the object identity of such an extracted method.

# Domenic Denicola (9 years ago)

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Brendan Eich

You're counting on the property assignment being moved into the constructor, where this is bound. In a class body in ES6 (without property assignment extension), especially in the top level where method defintiions go, this isn't obviously bound to the newly constructed instance.

Ok, that's kind of a nit, or an observation. No worries.

Yeah, just to highlight this, the property initializer syntax is very far from reaching consensus, and I wouldn't take that for granted and then ask if we can build something else on top of it.

Bigger question is what we want: method per instance allocation cost, which what you did imposes? Or something that can be more efficiently implemented, such as what Strong/SoundScript proposes (last I looked). The latter is what Java and C++ do. Then the trick is enabling first-class function extraction from method, which is a pay-for-what-you-ask-for alternative to allocation per method per constructed instance.

Agreed. The pattern shown is really an antipattern in my book (and according to conventional JavaScript wisdom). My understanding is that React encourages this antipattern, but that's not something we should encourage at a language level. (Which is part of why property initializer syntax may not make it, at least not in the form you show).

# Matthew Robb (9 years ago)

What I'd really like to have in the language is the ability to store a property access into a single binding:

let someObj = { doStuff(){} };

let doStuff = #someObj.doStuff;

doStuff();

Treated as:

let someObj = { doStuff(){} };

someObj.doStuff();
  • works with any property access
  • could help simplify some existing code bases: polymer/observe-js#path-objects
  • for functions it would allow call/apply or bind to still work if needed

Now I realize this feature is more than syntactic sugar and would have to work more like expression pointers but I can't see how the machinery of this would need to be that much different than something like module bindings.

  • Matthew Robb
# Andrea Giammarchi (9 years ago)

FWIW I've just added an extra possible solution to what is a very common problem: zenparsing/es-function-bind#17

it uses mixins, but I would personally vote +1 to have ::obj.method returning every time the same method.

Best

# Sebastian Markbåge (9 years ago)

Domenic, would you care to propose an alternative that is concise and memory efficient if it is an anti-pattern?

That would be helpful and constructive (your comment, not so much).

# Sebastian Markbåge (9 years ago)

Brendan, "the pay for what you ask for" model isn't very efficient when you keep asking for the same thing multiple times (like React is doing in its frequently executed render function). We want it to at least be memoized (presumably in a slot on the instance). Lazily creating it is an unobservable implementation detail.

# Domenic Denicola (9 years ago)

I don't think this is possible to do in a memory-efficient way. I thus think it should not be easy, nor concise. Doing inefficient things should be painful and discouraged.

# Sebastian Markbåge (9 years ago)

On Fri, Jul 17, 2015 at 4:17 PM, Domenic Denicola <d at domenic.me> wrote:

I don't think this is possible to do in a memory-efficient way. I thus think it should not be easy, nor concise. Doing inefficient things should be painful and discouraged.

Funny. That's what I think about Promises, but I recognize it as an important use case for some people, and am happy to support it until I can come up with an prove a good alternative.

Besides, this is not different than arrow functions or closures in general. In fact, this can allocate the memory for the function ahead of time instead of having a separate allocation for an arrow function and the instance.

# Bergi (9 years ago)

Matthew Robb schrieb:

What I'd really like to have in the language is the ability to store a property access into a single binding

Notice that the zenparsing/es-function-bind proposal does exactly this, at least for methods (and I don't think I would want it for arbitrary assignments). Your example code would look like this:

 let someObj = { doStuff(){} };

 let doStuff = ::someObj.doStuff;

 doStuff();

Bergi