Skip to content

Instantly share code, notes, and snippets.

@ZacharyRSmith
Created March 18, 2018 21:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZacharyRSmith/026575022c593bb5d08effee6b54eac5 to your computer and use it in GitHub Desktop.
Save ZacharyRSmith/026575022c593bb5d08effee6b54eac5 to your computer and use it in GitHub Desktop.
descriptor pattern
const assert = require('assert');
class Descriptor {
set(instance, value) {
instance[this.name] = value;
}
}
class Grade extends Descriptor {
set(instance, value) {
if (!(0 <= value && value <= 100)) throw new Error(`Value must be between 0 and 100 but was "${value}".`);
super.set(instance, value);
}
}
function useDescriptors(Class) {
return new Proxy(this, {
set: function (obj, prop, value) {
if (Class[prop] instanceof Descriptor) {
Class[prop].set(obj, value);
} else {
return Reflect.set(...arguments);
}
}
});
}
class Exam {
constructor() {
// ALT?: extend a class that does this?
// Or Proxy constructor?
return useDescriptors.call(this, Exam);
}
}
Exam.writingGrade = new Grade();
Exam.scienceGrade = new Grade();
Object.keys(Exam).forEach(k => {
const v = Exam[k];
if (!(v instanceof Descriptor)) return;
v.name = k;
});
class Homework {
constructor() {
return useDescriptors.call(this, Homework);
}
}
Homework.grade = new Grade('grade');
Object.keys(Homework).forEach(k => {
const v = Homework[k];
if (!(v instanceof Descriptor)) return;
v.name = k;
});
const firstExam = new Exam();
firstExam.writingGrade = 82;
firstExam.scienceGrade = 99;
const secondExam = new Exam();
secondExam.writingGrade = 75;
assert.equal(firstExam.writingGrade, 82);
assert.equal(firstExam.scienceGrade, 99);
assert.equal(secondExam.writingGrade, 75);
assert.throws(() => { secondExam.writingGrade = 101 });
assert.throws(() => { secondExam.scienceGrade = 101 });
const homework = new Homework();
homework.grade = 90;
assert.equal(homework.grade, 90);
assert.throws(() => { homework.grade = 101 });
assert.deepEqual(Object.keys(homework), ['grade']);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment