Использование Proxy в классах
Решил позабавиться, сделать бесконечные range-массивы с поддержкой простейших операций.
Идея примерно следующая:
Сделать возможность создавать URange обьекты, которые являются "бесконечными массивами", которые можно складывать умножать и тд.
Пока получилось примерно следущее, но я пока никак не могу придумать, как перевести эту идею в ООП стиль. Потому что, пока что у меня есть лишь генерирующая обьекты функция и набор функций преобразования. А хотелось бы, чтобы можно было вызывать их как методы, пусть даже и возвращающие новые обьекты без изменения собственного состояния.
Вопрос в общем то в том, а можно ли вообще каким-то образом что-то подобное осуществить, тспользуя Proxy?
function URange(start, step) {
const uArray = new Proxy([], {
get: ((target, p) => {
if (p.startsWith('__')) {
return target[p];
}
if (p % 1) {
return undefined;
}
return start + step * p
}),
has: ((target, p) => p % 1 === 0)
});
uArray.__step = step;
uArray.__start = start;
return uArray;
}
function addUp(range1, range2) {
const start = range1.__start + range2.__start;
const step = range1.__step + range2.__step;
const uArray = new Proxy([], {
get: ((target, p) => start + step * p),
has: ((target, p) => p % 1 === 0)
});
uArray.__step = step;
uArray.__start = start;
return uArray;
}
const uArr1 = URange(0, 4);
const uArr2 = URange(5, 15);
const sumUArr = addUp(uArr1, uArr2);
Array(10).fill("").forEach((_, i) => {console.log(uArr1[i], uArr2[i], sumUArr[i]);})
Ответы (1 шт):
Интересная задачка. Немного подхаченный вариант решения, который не на 100% надежный. Но в принципе, можно как-нибудь обойти прямой вызов конструктора и пожестче.
class URange {
static construct(start, step) {
const uRange = Object.create(URange.prototype);
return new Proxy(uRange, {
get: ((target, p) => {
if (Number.isNaN(+p)) {
return target[p];
}
return start + step * p;
}),
has: ((target, p) => p % 1 === 0)
})
}
constructor() {
throw new Error('Direct constructor call are forbidden. Use "URange.construct(start, step)" instead');
}
add(uRange, index) {
return this[index] + uRange[index];
}
subtract(uRange, index) {
return this[index] - uRange[index];
}
multiply(uRange, index) {
return this[index] * uRange[index];
}
divide(uRange, index) {
return this[index] / uRange[index];
}
}
const u1 = URange.construct(5, 5);
const u2 = URange.construct(3, 8);
const u3 = new URange();
for (let i = 0; i < 10; i++) {
console.log(u1[i], u2[i], u1.add(u2, i), u1.subtract(u2, i));
}