bublejs / buble

https://buble.surge.sh
MIT License
871 stars 67 forks source link

Support property initializer syntax for classes #123

Open purdrew opened 6 years ago

purdrew commented 6 years ago

A popular method for defining state and binding this context to methods in React is to use the proposed property initializer syntax to define them. Currently bublé does not recognize this syntax.

ES6 Syntax:

class Example extends Component {
  constructor() {
    super();

    this.state = {
      count: 0
    };

    this.increment = this.increment.bind(this);
  }

  increment() {
    this.setState({count: this.state.count + 1});
  }
}

With property initializer syntax:

class Example extends Component {
  state = {
    count: 0
  }

  increment = () => {
    this.setState({count: this.state.count + 1});
  }
}

Would love to see support for this in bublé as it condenses code and removes boilerplate. For comparison here is the babel plugin that supports it.

d-Pixie commented 6 years ago

Just ran into this problem when using react-styleguidist to document ... well React ...

The idiom in React is to use the property initializer syntax for things like propTypes, defaultProps and state and not being able to use this in react-styleguidist means the examples in the docs - compiled by Bublé - don't look like the actual code - compiled by Babel - we will write.

adrianheine commented 6 years ago

https://github.com/acornjs/acorn-class-fields could be used to parse this.

Makio64 commented 6 years ago

Any news on this features implementation ?

adrianheine commented 6 years ago

As far as I know nobody is working on this. If someone wants to pick this up I'm happy to mentor and help.

KutnerUri commented 6 years ago

This is also known as 'class properties'.

I am foreseeing a problem with arrow functions: class X { fun = () => { alert('fun') }; } might be transpiled as function X { this.fun = function() { alert('fun') }; } but I am expecting it to be transpiled as: function X { this.fun = function() { alert('fun') }.bind(this); }

but this seems to be a general problem with arrow functions.

KutnerUri commented 6 years ago

I don't understand why the standard says that properties should become part of the instance. I made more sense to transpile it like this: class X { a = 3 } --> function X() {} X.prototype.a =3

adrianheine commented 6 years ago

bublé generally knows how to handle this with arrow functions. Example:

class X {
  constructor() {
    this.fun = () => { alert(this.string) };
  }
}

is transpiled as

var X = function X() {
  var this$1 = this;

  this.fun = function () { alert(this$1.string) };
};

I think it should be easy to follow this with class fields.

If you wouldn't copy the field value to each instance all instances would share the same value. Example:

class StringBuf {
  parts = []
  push(str) { this.parts.push(str) }
}

You wouldn't expect all StringBuf instances to share a parts field.

KutnerUri commented 6 years ago

huh, I see. Since functions are stateless they would be ok, but properties would conflict between instances. Still feels there should be a way to set proto properties, but it's beside the point.

I hope I could clear some time to write the class properties, I will ping you when I do :)

adrianheine commented 6 years ago

Functions are just objects and can have properties as well:

const x = { a() { console.log(x.a.f) } }
x.a.f = 'hello'
x.a()

It would be great if you could start working on this!

trusktr commented 4 years ago

Still no class fields?