-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use traits in an ES6 class? #1
Comments
Hi @hackel. I'm myself new to First of all, "use strict";
const Trait = require("traits.js"); // using CommonJS as we don't support es6 modules yet
const EnumerableTrait = Trait({
each: Trait.required,
map(fun) {
let r = [];
this.each(e => { r.push(fun(e)); });
return r;
},
inject(init, accum) {
let r = init;
this.each(e => { r = accum(r, e)});
return r;
}
});
const Range = function(from, to) {
return Trait.create(
Object.prototype, // the prototype is insignificant in trait resolution
Trait.compose(
EnumerableTrait,
Trait({
each(fun) {
for (var i = from; i < to; i++) {
fun(i);
}
}
})
)
);
}
console.log(
new Range(0,5).inject(0, (a,b) => a+b) // new is optional
); Now, if you have a large code base already using classes, then you need to alter their constructors a bit. class EnumerableTrait
{
constructor() { ... }
// WE CAN NOT REFERENCE AN EXTERNAL FUNCTION IN A ES6 CLASS
each(fun) = Trait.required; // Syntax error We have to change the default object returned from the constructor. class EnumerableTrait
{
constructor() {
return Trait.compose(Trait(EnumerableTrait.prototype), Trait({
each: Trait.required // should be provided by the composite
}));
}
map(fun) { /* not used */; }
inject(init, accum) {
let r = init;
this.each(e => { r = accum(r, e)});
return r;
}
} Did we go the es5 route, then we would just set the required method name in the prototype. function EnumerableTrait() {
return Trait(EnumerableTrait.prototype);
}
EnumerableTrait.prototype = {
constructor: EnumerableTrait,
map: function(fun) { /* not used */; },
inject: function(init, accum) {
var r = init;
this.each(function(e) {
r = accum(r, e);
});
return r;
},
each: Trait.required // <- EACH IS REQUIRED
} The two examples are identical, in that they will both produce the following object when instantiated with { constructor:
{ value: [Function: EnumerableTrait],
writable: true,
enumerable: false,
configurable: true,
method: true },
map:
{ value: [Function: map],
writable: false,
enumerable: false,
configurable: false,
method: true },
inject:
{ value: [Function: inject],
writable: false,
enumerable: false,
configurable: false,
method: true },
each: { value: undefined, enumerable: false, required: true }
} The last bit is the class Range
{
constructor(from, to)
{
return Trait.create(
Object.prototype, // the prototype is insignificant in trait resolution
Trait.compose(
new EnumerableTrait, // () is optional when there is no arguments
Trait({
each(fun) {
for (var i = from; i < to; i++) {
fun(i);
}
}
})
)
);
}
} console.log(
new Range(0,5).inject(0, (a,b) => a+b) // new is NOT optional
); While it is possible to use |
@dotnetCarpenter Thanks for your very thorough response! I will play with this and see what I can do. I'm not about to say which method is superior, but the syntactic sugar of es6 classes definitely makes it easier for those coming from other languages (php, java, etc.), and I think it looks a bit more elegant than using object literals, but that's just me. |
@hackel, well (again) here is the es6 object literal version for comparison: const EnumerableTrait = Trait({
each: Trait.required,
map(fun) {
let r = [];
this.each(e => { r.push(fun(e)); });
return r;
},
inject(init, accum) {
let r = init;
this.each(e => { r = accum(r, e)});
return r;
}
});
const Range = function(from, to) {
return Trait.create(
Object.prototype,
Trait.compose(
EnumerableTrait,
Trait({
each(fun) {
for (var i = from; i < to; i++) {
fun(i);
}
}
})
)
);
}
console.log(
new Range(0,5).inject(0, (a,b) => a+b) // new is optional
); If you're new to JS, you should know that |
I'm wondering how traits.js should be used in a class, in order to achieve the equivalent of:
class Range(from, to) extends Object uses Enumerable
In the example from the documentation, I am guessing something like this would work:
Please let me know if I'm on the right track with this. Would love to use traits in my ES6 projects.
The text was updated successfully, but these errors were encountered: