#javascript #getter-setter #es6-class #es6-proxy
#javascript #getter-сеттер #es6-класс #es6-прокси
Вопрос:
Прокси можно использовать для определения «общих геттеров» для объектов. Например
var obj = {'a':3, 'b':4 };
var proxy = new Proxy( obj, {
get: function(obj, prop){return obj[prop] 10}
} );
proxy.a //13
У меня есть векторный класс, который расширяет Array
:
class vec extends Array{
constructor(...a){
super(...a)
}
get x(){
return this[0];
}
/* some more functions */
}
и я хочу, чтобы индекс обтекался, как в python. Например, if v
— это вектор, который я хочу v[-1]
вернуть последним элементом v
. Для этого мне нужно было бы обернуть прокси вокруг каждого экземпляра vector (я думаю), чтобы я мог ограничить индекс. Но я не знаю, как создать прокси для всех экземпляров, я знаю только, как это работает для одного объекта. Итак, как бы вы это сделали?
Комментарии:
1. Допустимо возвращать объект из функции-конструктора, или вы можете использовать фабричную функцию.
Ответ №1:
Вы могли бы создать свой класс так, чтобы он возвращал экземпляр прокси, и на этом прокси вы создаете метод get, в который добавляете свою пользовательскую логику.
class Vec extends Array {
constructor(...a) {
super(...a)
return new Proxy(this, {
get: function(target, prop, receiver) {
const n = prop;
if (!isNaN(n) amp;amp; n < 0) {
return [...target].slice(n)
}
return Reflect.get(...arguments);
}
})
}
get x() {
return this[0];
}
}
const v = new Vec(1, 2, 3);
console.log(v[-1])
console.log(v[-2])
console.log(v.x)
Комментарии:
1. Я не думаю
[...target].slice(n)
, что делает то, что хочет OP2. Кажется, это делает то, что я хочу, и кажется, что это правильный способ сделать это .. Поведение среза не то, что (я хочу взять модуль индекса, чтобы зафиксировать его между 0… (arr.length-1) ) но это внесло бы быструю модификацию. Спасибо!
Ответ №2:
Я хочу
v[-1]
вернуть последний элементv
.
Кажется, у вас Vector
фиксированный размер (например, 3 для .x
, .y
и .z
), поэтому вы могли бы просто определить другой геттер с именем -1
.
В общем, я бы рекомендовал следовать предложению относительной индексации и просто реализовать .at()
метод или предложение массива .last
.
Я не знаю, как создать прокси для всех экземпляров
Вы можете сделать свой прототип прокси-сервером:
vec.prototype = new Proxy(vec.protoype, {
get(target, prop, receiver) {
if (typeof prop == "string" amp;amp; prop[0] == '-') {
const i = Number(prop);
if (Number.isInteger(i)) {
return receiver[receiver.length i];
}
}
return Reflect.get(target, prop, receiver)
}
});
Комментарии:
1. Мой класс работает как массив, поэтому он может иметь любую длину. Метод x() — это просто сокращение. Мне нравится этот ответ, но ответ Ненада немного ближе к тому, что я хочу.
2. Так ли это? Вы запросили один прокси для всех экземпляров, и это именно то, что делает мой ответ (но решение Nenad этого не делает).
3. Ну, я не был уверен, каков наилучший способ его реализации, у меня просто было смутное представление о том, чего я хотел. Теперь, когда я думаю об этом, может быть, наличие одного прокси в прототипе дает лучшую производительность? Я подумаю об этом еще немного, но сейчас ответ Ненада остается принятым.
4. Я бы надеялся, что это так, но я бы проверил его, чтобы быть уверенным. В любом случае, даже если вы создаете по одному прокси для каждого экземпляра, я бы рекомендовал передавать один и тот же объект-обработчик всем им.