我想做这样的事情:
let DOM = {
slide1: {
button: ".btn",
box: "#box"
}
}
然后当我写下:
console.log(DOM.slide1.box);
我希望输出为
"#slide1 #box"
。
经过一番研究,我尝试使用 ES6 Proxy 对象,但问题并没有解决:
const dom_names = {
slide1: {
button: ".btn",
box: "#box"
}
}
const DOM_handler = {
get: (target, property, receiver)=>{
if(property == "slide1") return "#slide1";
return Reflect.get(...arguments);
}
}
const DOM = new Proxy(dom_names, DOM_handler);
在此实现之后,我认识到我需要编写以下内容才能获得我正在寻找的结果:
console.log(`${DOM.slide1} ${DOM.create.box}) // #slide1 #box
正如你所看到的,这是一个非常糟糕的方法,我正在考虑使用我的解决方案(使用代理),但问题是:我需要一种方法来知道“属性的属性”,我希望你能看到并明白我的意思。
有些人会说:使用您的第一个实现(没有代理的实现,意味着问题中的第一个代码),但使用
for
..of
循环来获取键名称。我会说,我想使用这个确切的代码:
DOM.slide1.box
获得此输出:
"#slide1 #box"
为什么?我为什么要做我正在做的事情?因为我需要一种在 JavaScript 中定义 HTML 类和 ID 的方法,这使得使用
document.querySelector
时变得更加轻松。另外,更改 HTML 文件中的类和 ID 名称的好处是,因此当我更改 HTML 文件中的类和 ID 名称时,我将不再需要重新因子(重新)(重写)(更改)较新的整个 JavaScript 文件中的类和 ID 名称。
虽然代理可以做到这一点,但还有一种更简单的方法:只需首先将正确的字符串值放入
DOM
的属性中即可。这仍然允许您按照自己的意愿访问它们:
const DOM = selectorHierarchy({
slide1: {
button: ".btn",
box: "#box"
}
});
function selectorHierarchy(obj, ancestors = []) {
for (var key in obj)
if (typeof obj[key] == "string")
obj[key] = [...ancestors, obj[key]].join(" ");
else if (typeof obj[key] == "object")
selectorHierarchy(obj[key], [...ancestors, '#'+key]);
return obj;
}
console.log(DOM.slide1.box)
这是可能的。一种简单的方法是递归地将代理应用于每个对象,然后在每次调用时传递私有属性,将遍历字符串化到叶子。
概念证明:
const deepProxyAll = (obj, proxyObj) => {
for (const k in obj) {
if (typeof obj[k] === "object") {
obj[k] = deepProxyAll(obj[k], proxyObj);
}
}
return new Proxy(obj, proxyObj);
};
const proxyObj = {
get: (target, property, receiver) => {
if (!target.hasOwnProperty(property)) {
throw new Error(`property '${property}' does not exist on object`);
}
else if (typeof target[property] === "object" &&
typeof target[property] !== "null") {
target[property]._str = target._str ?
`${target._str} ${property}` : `#${property}`;
return target[property];
}
return target._str ? `${target._str} ${target[property]}`
: `#${target[property]}`;
}
};
const obj = {
slide1: {
button: ".btn",
box: "#box",
foobar: {bar: {quux: {garply: 42}}}
},
test: "hello",
};
const DOM = deepProxyAll(obj, proxyObj);
console.log(DOM.slide1.box);
console.log(DOM.slide1.foobar.bar.quux.garply);
console.log(DOM.test);
代理功能强大,并且很容易改变对象属性访问的行为以适应各种突发奇想,但在采用这种方法作为核心设计之前,请批判性地思考其好处是否值得其缺点。