-
-
Save rauschma/1336846 to your computer and use it in GitHub Desktop.
// Roughly: a combination of Jeremy’s and Allen’s ideas, updated with the results of recent discussions | |
// Guidelines: | |
// - Don’t use the same syntax as for object literals, but stay close. | |
// - Rationale: Some object literal features are forbidden in class declarations => don’t confuse people | |
// - Rationale: Comma separation is a bit tricky. | |
// - Keep new features at a minimum | |
// - Don’t obscure the fact that private names are actually name objects. | |
// => They can also be imported from somewhere else – a use case that needs to be supported. | |
// - In order to minimize confusion, keep module syntax and class declaration syntax similar. | |
// Rules: | |
// - Use @ to refer to name objects | |
// - there is no syntactic sugar for `this.` | |
// Name objects: | |
// - Rough rule for what @foo means: “insert arbitrary identifier here”. | |
// - Used for property access and to name methods. | |
// - foo.@bar is syntactic sugar for foo[bar] | |
// - Rationale: immediately obvious that it’s property access | |
class Monster extends Being { | |
// Only methods are allowed here (because these are the prototype’s properties) | |
// Create name objects that only exist within the declaration’s scope | |
private age, health, incAge; | |
// Constructor | |
// Alternative: use the name "new". Caveat: super.new(name) looks a bit weird. | |
constructor(name, this.weight, this.@age, this.@health) { | |
super.constructor(name); | |
} | |
getNameObjectForAge() { | |
return age; | |
} | |
// private method | |
@incAge() { | |
this.@age++; | |
} | |
// getter | |
get strength() { | |
// stronger with increasing age... | |
return super.strength * this.@age; | |
} | |
} |
module name from "@name"; | |
// Alternatives: use <| operator, use a do-block | |
let Monster = function () { | |
let age = name.create(); | |
let health = name.create(); | |
let incAge = name.create(); | |
function Monster(name, weight, age, health) { | |
super.constructor(name); | |
this.weight = weight; | |
this[age] = age; | |
this[health] = health; | |
} | |
Monster.prototype = Object.create(Being.prototype); | |
Monster.prototype.constructor = Monster; | |
Monster.prototype.getNameObjectForAge = function () { | |
return age; | |
}; | |
Monster.prototype[incAge] = function () { | |
this[age]++; | |
} | |
Object.defineProperty(Monster.prototype, "strength", { | |
get: function () { | |
// stronger with increasing age... | |
return super.strength * this[age]; | |
} | |
}); | |
return Monster; | |
}(); |
You forgot the return
statement in the desugared section
Is it
Monster.prototype = Object.create(Being);
or
Monster.prototype = Object.create(Being.prototype);
?
@Raynos: Fixed, thanks.
@domenic: You are absolutely right. Fixed. Error-prone, looking forward to syntactic sugar...
I think you have problem with the desugaring because all methods (but at least the constructor) are non-enumerable, and to match object-initializer, method (not the constructor) should also be non-writable (but configurable), so it would be easier to desugar to one big
Object.create(Being.prototype, {
...
})
Not to mention constructor-inheritance, do you plan it as part of this proposal (then you should use <| when defining Monster function),
@Herby where does it say whether methods should be non-enumerable (only the constructor property should be)
@Herby, @Raynos: I expect the decision on whether or not to make methods non-enumerable (which is done by built-ins, but not by most of the userland code that I have seen) to be final fine-tuning. My first solution was a big Object.create() with property descriptors, but then you have to use [] for the private property names (for which there isn’t consensus, yet).
@Raynos: In draft ES6 spec, it says about object initializers that when short method syntax is used, they are created with enumerable = false, configurable = true and writable = false.
writable
false, hmmm, that seems to go against even built-ins. I imagine most would be against it, but IMO it'd be a good thing to force something more explicit (i.e. Object.defineProperty
) when overriding existing methods.
@domenic, that's exactly the logic behind those attribute choices for concise methods. If somebody has defined a property as a "method" it should take something more than an assignment to change it.
However, many people find the configurable: true & writable: false combination baffling so it is going to take some effort to keep it in the spec.
Can we have an example of the entire thing desugared?
I attempted to desugar it : https://gist.github.com/2151045