说我有这样的情况:
const foo = {
bar: {
star: {
guitar: 'geetar'
}
}
}
然后我有
const stew = {
moo: () => foo.bar.star.guitar
}
然后我在事件循环的下一个计时周期中致电moo:
process.nextTick(function(){
const guitar = stew.moo();
});
我的问题是-是否有任何方法/技巧来获取路径的字符串表示形式:“ foo.bar.star.guitar”?
我可以用字符串替换代码:
const stew = {
moo: () => 'foo.bar.star.guitar'
}
但是我正在寻找一种获取字符串表示形式的方法。 一个重要的细节是,如果有人放入了不存在的对象路径,我想生成一条有用的错误消息。这就是获取字符串表示形式的全部目的-提供有用的错误消息。
答案 0 :(得分:1)
一种方法可能是使用减速器从提供的路径中提取值。对于诸如bar.star.guitar
之类的路径,您可以从对象中提取值geetar
:
const foo = {
bar: {
star: {
guitar: 'geetar'
}
}
}
通过以下方式:
const path = 'bar.star.guitar'; // Remove "foo" from your path
const foo = {
bar: {
star: {
guitar: 'geetar'
}
}
}
const value = path
.split('.') // Break path into parts, splitting by '.'
.reduce((currentObject, pathPart) => {
// Iterate through each part of the path in order, and incrementally
// extract and return corresponding value of currentObject if it
// exists. Repeat this for each path part until we find value from
// input object at end of the path
if(currentObject) {
currentObject = currentObject[ pathPart ]
}
return currentObject
}, foo);
console.log('path: ', path, 'value:', value)
这里的想法是依次遍历输入路径的每个“部分”(即用“。”分隔的字符串),并逐步提取并返回与正在处理的输入对象的部分(键)相对应的值。我们逐步地继续执行此过程,直到到达路径的尽头,这时我们将达到所需的值(如果存在)
答案 1 :(得分:1)
这是针对图书馆的,所以我除了这里没有其他信息:
const stew = {
moo: () => foo.bar.star.guitar
}
所以我能做的一件事是:
let guitar;
try{
guitar = stew.moo();
}
catch(err){
console.error('Could not get value from:', stew.moo.toString());
}
aka,只需记录该函数的字符串表示形式。对于用户来说,这是足够好的信息,因此必须调试问题。
有关完整演示,请参阅: https://gist.github.com/ORESoftware/5a1626037cb8ba568cdffa69374eac1d
答案 2 :(得分:1)
const stew = {
moo: () => foo.bar.star.guitar
}
stew.moo.toString().match(/([a-z0-9_$]+\.?)+/)[0]
// returns "foo.bar.star.guitar"
这在某种程度上取决于人们总是使用相同的功能。另外,我只是为有效的函数名称使用了简写形式-实际的正则表达式会更长。.What characters are valid for JavaScript variable names?
答案 3 :(得分:1)
根据您对此的评论,以获取有用的错误消息,我相信您可以摆脱Error.captureStackTrace
const er = {};
Error.captureStackTrace(er);
const foo = {
bar: {
star: {
guitar: "geetar"
}
}
};
const a = foo.bar.nope.guitar;
console.log(er.stack);
记录
const a = foo.bar.nope.guitar;
^
答案 4 :(得分:1)
如果您能够控制人们可以引用的根变量,则可以将它们包装在Proxy对象中,该对象始终跟踪属性访问,如下所示:
function callStackTracker(propsSoFar) {
return {
get: function(obj, prop) {
if (prop in obj) {
return typeof obj[prop] === "object" ?
new Proxy(obj[prop], callStackTracker(propsSoFar.concat(prop))) :
obj[prop];
} else {
throw new Error("Couldn't resolve: " + propsSoFar.concat(prop).join('.'));
}
}
};
};
let foo = {
bar: {
star: {
guitar: 'geetar'
}
}
}
foo = new Proxy(foo, callStackTracker(['foo']));
console.log(foo.bar.star.guitar); // "geetar"
console.log(foo.bar.star.clarinet); // Error: Couldn't resolve: foo.bar.star.clarinet
console.log(foo.bar.boat); // Error: Couldn't resolve: foo.bar.boat
然后在此示例中,我将这个已解决的路径作为错误抛出,但是您可以使用它做任何您想做的事情。