JavaScript 中的自定义数组 getter
Custom Array-like getter in JavaScript
我有一个简单的 ES6 class,像这样:
class Ring extends Array {
insert (item, index) {
this.splice(index, 0, item);
return this;
}
}
我想让 Ring 对象的索引环绕,这样 new Ring(1, 2, 3)[3]
returns 1,new Ring(1, 2, 3)[-1]
returns 3,依此类推。这在 ES6 中可行吗?如果是这样,我将如何实施?
我读过代理,它允许完全自定义 getter,但我不知道如何将代理应用于 class。我确实做到了:
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
现在是一个支持环绕索引的 Ring 对象。问题是我每次都必须这样定义 Ring 对象。有没有办法将此代理应用到 class 以便调用 new Ring()
returns 它?
警告:这是一个丑陋的 hack
仔细想想,这是一个相当简单的方法。
function ClassToProxy(_class, handler) {
return (...args) => new Proxy(new _class(...args), handler);
}
这定义了一个函数ClassToProxy
。第一个参数是您想要添加行为的 class,第二个是处理程序。
这是用法示例:
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;
}
}
你基本上有两个选择:
在每个实例周围包裹一个 Proxy
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
原型周围包裹一个 Proxy
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];
}
});
我有一个简单的 ES6 class,像这样:
class Ring extends Array {
insert (item, index) {
this.splice(index, 0, item);
return this;
}
}
我想让 Ring 对象的索引环绕,这样 new Ring(1, 2, 3)[3]
returns 1,new Ring(1, 2, 3)[-1]
returns 3,依此类推。这在 ES6 中可行吗?如果是这样,我将如何实施?
我读过代理,它允许完全自定义 getter,但我不知道如何将代理应用于 class。我确实做到了:
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
现在是一个支持环绕索引的 Ring 对象。问题是我每次都必须这样定义 Ring 对象。有没有办法将此代理应用到 class 以便调用 new Ring()
returns 它?
警告:这是一个丑陋的 hack
仔细想想,这是一个相当简单的方法。
function ClassToProxy(_class, handler) {
return (...args) => new Proxy(new _class(...args), handler);
}
这定义了一个函数ClassToProxy
。第一个参数是您想要添加行为的 class,第二个是处理程序。
这是用法示例:
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;
}
}
你基本上有两个选择:
在每个实例周围包裹一个
Proxy
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
原型周围包裹一个Proxy
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]; } });