Skip to content

Instantly share code, notes, and snippets.

@rauschma
Created November 3, 2011 15:52
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save rauschma/1336846 to your computer and use it in GitHub Desktop.
Save rauschma/1336846 to your computer and use it in GitHub Desktop.
A minimal class proposal for ECMAScript.next
// 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;
}();
@Raynos
Copy link

Raynos commented Mar 21, 2012

You forgot the return statement in the desugared section

@domenic
Copy link

domenic commented Mar 21, 2012

Is it

Monster.prototype = Object.create(Being);

or

Monster.prototype = Object.create(Being.prototype);

?

@rauschma
Copy link
Author

@Raynos: Fixed, thanks.

@rauschma
Copy link
Author

@domenic: You are absolutely right. Fixed. Error-prone, looking forward to syntactic sugar...

Copy link

ghost commented Mar 21, 2012

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),

@Raynos
Copy link

Raynos commented Mar 21, 2012

@Herby where does it say whether methods should be non-enumerable (only the constructor property should be)

@rauschma
Copy link
Author

@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).

Copy link

ghost commented Mar 21, 2012

@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.

@domenic
Copy link

domenic commented Mar 22, 2012

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.

@allenwb
Copy link

allenwb commented Mar 22, 2012

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment