获取对象路径的字符串表示形式

时间:2018-11-22 23:41:31

标签: javascript node.js

说我有这样的情况:

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'
    }

但是我正在寻找一种获取字符串表示形式的方法。 一个重要的细节是,如果有人放入了不存在的对象路径,我想生成一条有用的错误消息。这就是获取字符串表示形式的全部目的-提供有用的错误消息。

5 个答案:

答案 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

然后在此示例中,我将这个已解决的路径作为错误抛出,但是您可以使用它做任何您想做的事情。