wycats / javascript-decorators

2.4k stars 127 forks source link

decorator for variables #32

Open yongxu opened 9 years ago

yongxu commented 9 years ago

Hey there,

I tried today using babel and realize it doesn't work:

@decorator
let somethingWorkLikeClass = aFunctionThatReturnsObject();

Babel will raise SyntexError: Leading decorator must be attached to a class declaration.

I think it would be very useful to have decorators work on variable, especially when work with some other new features like Object.observe() and decorate class returned by a factory function.

sebmck commented 9 years ago

Isn't this ambiguous when you have more than one declarator?

yongxu commented 9 years ago

Hey @sebmck, I couldn't see why it might be ambiguous, could you give an example? Thanks!

sebmck commented 9 years ago
@decorator
let somethingWorkLikeClass = aFunctionThatReturnsObject(), foo = "bar";
yongxu commented 9 years ago

Thanks @sebmck, yeah I see the problem now, but I feel it is probably still better to either decorate all the variables or throw an exception just under this special case. I think there are a lot potential using decorator with Object.observe or decorating a returned object.

loganfsmyth commented 9 years ago

@yongxu What does this provide that is not covered by doing

let somethingWorkLikeClass = decorator(aFunctionThatReturnsObject());

though?

yongxu commented 9 years ago

@loganfsmyth Yes, that is actually what I did when I found out decorator doesn't work on variables. I just think it would be great to apply decorator on variables. I think decorator will make code much cleaner if we use if for higher order components, or distinguish difference between use a variable as function input and extend a variable to make it more powerful(such as polyfill and wrapper)

nevir commented 8 years ago

Allowing decorators on assignment (and/or export) expressions would certainly help for more complicated decoration, while still being easy to read:

@memoize({ttl: 30})
export function getStuff(id) {
  ...
}

Instead of:

export const getStuff = memoize({ttl: 30})(function getStuff(id) {
  ...
});
jkrems commented 8 years ago

There's also the unfortunate "function naming" thing. The only way to have named functions with "decorators" is the following right now:

export const getStuff = memoize({ ttl: 30 })(function getStuff(id) {});

Compared to (given fn.name semantics for assignments):

@memoize({ ttl: 30 })
export const getStuff = () => {}
D1plo1d commented 8 years ago

Yes the @memoize syntax is much more readable for me as well. The readability problem of the current syntax compounds when you try to use multiple decorators.

Class decorators have been used by the React community extensively in the form of so-called Higher Order Components. Personally I have found Higher Order Components to promote a simpler coding style then mixins with more obvious boundaries between objects. I sincerely hope we can bring a syntax to encourage this coding style back into es7 through export decorators like @jkrems example.

sap9433 commented 8 years ago

Another use case . With react stateless component decorator doesn't work . same issue Leading decorators must be attached to a class declaration

@connect((state) => {
        return {
            someVAr: state.someStateProp
        };
    }
)
const Layer = (props) => {
  return <div > hi  {this.props.someVAr}< /div>);
};
silkentrance commented 8 years ago

I think that this is pretty much the same as for free function decorators. Hoisting might be a problem here.

And, in accordance to your overall stance towards free function decorators, this should be a won't fix and should be closed (for future review of course, once we get rid of that annoying hoisting feature) in order to get this going again.

Hypnosphi commented 6 years ago

Hoisting might be a problem here

let and const aren't hoisted