JavaScript中类似getter的自定义数组
我有一个简单的ES6课程,如下所示:JavaScript中类似getter的自定义数组,javascript,ecmascript-6,es6-class,es6-proxy,Javascript,Ecmascript 6,Es6 Class,Es6 Proxy,我有一个简单的ES6课程,如下所示: class Ring extends Array { insert (item, index) { this.splice(index, 0, item); return this; } } 我想使环形对象的索引换行,以便new-Ring(1,2,3)[3]返回1,new-Ring(1,2,3)[-1]返回3,依此类推。这在ES6中可能吗?如果是,我将如何实施 我读过关于代理的书,它允许完全定制的getter
class Ring extends Array {
insert (item, index) {
this.splice(index, 0, item);
return this;
}
}
我想使环形对象的索引换行,以便new-Ring(1,2,3)[3]
返回1,new-Ring(1,2,3)[-1]
返回3,依此类推。这在ES6中可能吗?如果是,我将如何实施
我读过关于代理的书,它允许完全定制的getter,但我不知道如何将代理应用于类。我确实做到了:
var myRing = new Proxy (Ring.prototype, {
get: function (target, name) {
var len = target.length;
if (/^-?\d+$/.test(name))
return target[(name % len + len) % len];
return target[name];
}
});
myRing
现在是一个支持环绕索引的环形对象。问题是我每次都必须定义这样的环形对象。是否有方法将此代理应用于类,以便调用new Ring()
返回它?警告:这是一个丑陋的黑客行为
仔细想想,这是一个相当简单的方法
function ClassToProxy(_class, handler) {
return (...args) => new Proxy(new _class(...args), handler);
}
这定义了一个函数ClassToProxy
。第一个参数是要添加行为的类,第二个参数是处理程序
下面是使用示例:
const Ring = ClassToProxy(
// Class
class Ring {
constructor(...items) {
this.items = items;
}
},
// Handler
{
get: function(target, name) {
return target.items[name];
}
}
)
基本上是这样
class ProxyRing extends Array {
constructor(...args) {
super(...args)
return new Proxy(this, {
get: function (target, name) {
var len = target.length;
if (typeof name === 'string' && /^-?\d+$/.test(name))
return target[(name % len + len) % len];
return target[name];
}
});
}
insert (item, index) {
this.splice(index, 0, item);
return this;
}
}
您基本上有两种选择:
- 在每个实例周围环绕一个
代理
const handler = { get(target, name) { var len = target.length; if (typeof name === 'string' && /^-?\d+$/.test(name)) return target[(name % len + len) % len]; return target[name]; } }; class Ring extends Array { constructor() { super() return new Proxy(this, handler); } … }
- 围绕类的原型包装一个
代理
class Ring extends Array { constructor() { super() } … } Ring.prototype = new Proxy(Ring.prototype, { get(target, name, receiver) { var len = target.length; if (typeof name === 'string' && /^-?\d+$/.test(name)) { if (+name < 0) return receiver[(name % len) + len]; if (+name > len-1) return receiver[name % len]; } return target[name]; } });
类环扩展数组{ 构造函数(){ 超级() } … } Ring.prototype=新代理(Ring.prototype{ 获取(目标、名称、接收者){ var len=target.length; if(typeof name==='string'&&/^-?\d+$/.test(name)){ 如果(+名称<0) 返回接收方[(名称%len)+len]; 如果(+name>len-1) 返回接收方[名称%len]; } 返回目标[名称]; } });
newproxy(…)
,并使用new
调用它即可。是的,没有代理你不能这么做。嗯。。。这非常接近,只是它不支持new
。。。这似乎是完美的工作!我没有意识到构造函数可以显式返回值…嗯。。。哇,我从来不知道你可以从ES6类的构造函数中返回一个值……是的。在大多数情况下,这是不合理的,但事实正是如此。第二种方法似乎对我不起作用。我尝试仅使用代理部分来扩展Number类,并通过将Number.prototype
的两个实例都更改为Number.prototype.\uuuuuuuuu
@ETHproductions.我不确定为什么要将Number.prototype
设置为代理来实现这一点?您可能应该更改。\uuuu proto\uuuu
,因为这会在原型链中引入另一个对象。