我可以像在 C# 中一样在自定义类上使用方括号吗? 或者 JavaScript 中的方括号仅限于数组?
C# 中的等效内容如下:
public class Contact
{
private string[] address = new string[3];
public string this[int index]
{
get
{
return address[index];
}
set
{
address[index] = value;
}
}
}
最佳答案
JavaScript 和 TypeScript 都没有您正在寻找的特定功能,但 JavaScript 确实有 Proxy
对象,它们非常强大并且可以用于此目的。您需要实现 get
和 set
陷阱处理程序(至少),并让 Contact
构造函数返回代理而不是实例本身。 (如果从构造函数返回一个对象,则会覆盖返回新创建的实例的默认行为。)在代理上“读取”的每个属性上都会调用 get
处理程序,并且 >set
处理程序在代理上的每个属性“write”上被调用:
// ==== The implementation
const rexAllDigits = /^\d+$/;
const contactProxyHandlers = {
get(target, key) {
if (rexAllDigits.test(key)) {
return target.address[key];
}
return target[key];
},
set(target, key, value) {
if (rexAllDigits.test(key)) {
return Reflect.set(target.address, key, value);
}
return Reflect.set(target, key, value);
}
};
class Contact {
constructor() {
this.address = ["", "", ""];
return new Proxy(this, contactProxyHandlers);
}
}
// ==== Usage:
const c = new Contact();
c[0] = "address 0";
console.log(c[0], c.address[0]); // "address 0", "address 0"
c.example = "not an index property";
console.log(c.example);
在该示例中,我将使用全数字属性名称的所有属性获取和设置重定向到 Contact
对象上的 address
数组,但传递请求对于其他属性,直接传递给对象。
您的 C# 版本将地址
设为私有(private)。很快您就可以使用 private fields在 JavaScript 中也可以做到这一点。在那之前,如果您想将其设为私有(private),可以使用 WeakMap
来实现,如下所示:
// ==== The implementation -- private parts
// You'd keep these parts private, for instance in a module and not exported
const contactAddresses = new WeakMap();
const proxyTargets = new WeakMap();
const rexAllDigits = /^\d+$/;
const contactProxyHandlers = {
get(target, key) {
if (rexAllDigits.test(key)) {
return contactAddresses.get(target)[key];
}
return target[key];
},
set(target, key, value) {
if (rexAllDigits.test(key)) {
return Reflect.set(contactAddresses.get(target), key, value);
}
return Reflect.set(target, key, value);
}
};
// ==== The implementation -- public parts
// You'd make this available, for instance exporting it from the module
class Contact {
constructor() {
// Initialize the entry in the map. If/when this object is ready
// for garbage collection, the entry will get removed automatically.
contactAddresses.set(this, ["", "", ""]);
const p = new Proxy(this, contactProxyHandlers);
proxyTargets.set(p, this);
return p;
}
showAddresses() {
const t = proxyTargets.get(this);
if (!t) {
throw new Error("Invalid `this` value for Contact");
}
console.log(JSON.stringify(contactAddresses.get(t)));
}
}
// ==== Usage:
const c = new Contact();
c[0] = "address 0";
console.log(c[0]); // "address 0"
c.showAddresses(); // "address 0", "", ""
c.example = "not an index property";
console.log(c.example);
使用私有(private)字段的版本还需要 proxyTargets
WeakMap
。它看起来像这样:
// ==== The implementation
class Contact {
static #rexAllDigits = /^\d+$/;
static #contactProxyHandlers = {
get(target, key) {
if (Contact.#rexAllDigits.test(key)) {
return target.#address[key];
}
return target[key];
},
set(target, key, value) {
if (Contact.#rexAllDigits.test(key)) {
return Reflect.set(target.#address, key, value);
}
return Reflect.set(target, key, value);
}
};
static #proxyTargets = new WeakMap();
#address = ["", "", ""];
constructor() {
const p = new Proxy(this, Contact.#contactProxyHandlers);
Contact.#proxyTargets.set(p, this);
return p;
}
showAddresses() {
const t = Contact.#proxyTargets.get(this);
if (!t) {
throw new Error("Invalid `this` value for Contact");
}
console.log(JSON.stringify(t.#address));
}
}
// ==== Usage:
const c = new Contact();
c[0] = "address 0";
console.log(c[0]); // "address 0"
c.showAddresses(); // "address 0", "", ""
c.example = "not an index property";
console.log(c.example);
关于javascript - 是否可以在 JavaScript 或 TypeScript 的自定义类中实现索引器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63613518/