Get string representation of object path












1















Say I have a situation like this:



const foo = {
bar: {
star: {
guitar: 'geetar'
}
}
}


and then I have:



const stew = {
moo: () => foo.bar.star.guitar
}


then I call moo in the next tick of the event loop:



process.nextTick(function(){
const guitar = stew.moo();
});


my question is - is there any way/trick to get the string representation of the path: "foo.bar.star.guitar"?



I could replace the code with a string:



    const stew = {
moo: () => 'foo.bar.star.guitar'
}


but I am looking to find a way to get a string representation.
One important detail is that I want to generate a useful error message - if someone puts in an object path that doesn't exist. That is the whole purpose of getting a string representation - for a useful error message.










share|improve this question





























    1















    Say I have a situation like this:



    const foo = {
    bar: {
    star: {
    guitar: 'geetar'
    }
    }
    }


    and then I have:



    const stew = {
    moo: () => foo.bar.star.guitar
    }


    then I call moo in the next tick of the event loop:



    process.nextTick(function(){
    const guitar = stew.moo();
    });


    my question is - is there any way/trick to get the string representation of the path: "foo.bar.star.guitar"?



    I could replace the code with a string:



        const stew = {
    moo: () => 'foo.bar.star.guitar'
    }


    but I am looking to find a way to get a string representation.
    One important detail is that I want to generate a useful error message - if someone puts in an object path that doesn't exist. That is the whole purpose of getting a string representation - for a useful error message.










    share|improve this question



























      1












      1








      1


      1






      Say I have a situation like this:



      const foo = {
      bar: {
      star: {
      guitar: 'geetar'
      }
      }
      }


      and then I have:



      const stew = {
      moo: () => foo.bar.star.guitar
      }


      then I call moo in the next tick of the event loop:



      process.nextTick(function(){
      const guitar = stew.moo();
      });


      my question is - is there any way/trick to get the string representation of the path: "foo.bar.star.guitar"?



      I could replace the code with a string:



          const stew = {
      moo: () => 'foo.bar.star.guitar'
      }


      but I am looking to find a way to get a string representation.
      One important detail is that I want to generate a useful error message - if someone puts in an object path that doesn't exist. That is the whole purpose of getting a string representation - for a useful error message.










      share|improve this question
















      Say I have a situation like this:



      const foo = {
      bar: {
      star: {
      guitar: 'geetar'
      }
      }
      }


      and then I have:



      const stew = {
      moo: () => foo.bar.star.guitar
      }


      then I call moo in the next tick of the event loop:



      process.nextTick(function(){
      const guitar = stew.moo();
      });


      my question is - is there any way/trick to get the string representation of the path: "foo.bar.star.guitar"?



      I could replace the code with a string:



          const stew = {
      moo: () => 'foo.bar.star.guitar'
      }


      but I am looking to find a way to get a string representation.
      One important detail is that I want to generate a useful error message - if someone puts in an object path that doesn't exist. That is the whole purpose of getting a string representation - for a useful error message.







      javascript node.js






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 23 '18 at 8:48







      Alexander Mills

















      asked Nov 22 '18 at 23:41









      Alexander MillsAlexander Mills

      18.8k32154317




      18.8k32154317
























          5 Answers
          5






          active

          oldest

          votes


















          1














          One approach could be to use a reducer to extract the value from a supplied path. For a path such as bar.star.guitar, you could extract the value geetar from object:



          const foo = {
          bar: {
          star: {
          guitar: 'geetar'
          }
          }
          }


          via the following:






          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)





          The idea here is to iterate in order through each "part" (ie string separated by '.') of the input path, and incrementally extract and return the value corresponding to the part (key) of the input object being processed. We incrementally continue this process until the end of the path is reached, at which point we arrive at the desired value (if it exists)






          share|improve this answer


























          • I don't understand this answer - I don't have 'foo.bar.star.guitar' as a string. I don't have that info. All I know is whether the object resolved or it threw an error "cannot read property x of undefined'.

            – Alexander Mills
            Nov 23 '18 at 0:10













          • @AlexanderMills right - so you have some arbitrary path string, and you need to extract the value corresponding to that path from input object? The snippet above is intended to illustrate how this can be done in general terms. Also, something to be aware of is that the path foo.bar.star.guitar is actually invalid for the object foo in your OP. Is there a format that you would prefer this answer to be presented in?

            – Dacre Denny
            Nov 23 '18 at 0:37






          • 1





            Your answer is how to resolve foo.bar.star.guitar from 'foo.bar.star.guitar'. But the question is about how to infer 'foo.bar.star.guitar' from foo.bar.star.guitar, for generating error messages for improper object access.

            – Lauren
            Nov 23 '18 at 7:34



















          1














          const stew = {
          moo: () => foo.bar.star.guitar
          }

          stew.moo.toString().match(/([a-z0-9_$]+.?)+/)[0]
          // returns "foo.bar.star.guitar"


          This somewhat depends on people always using the same kind of function. Also I just used a short-hand for valid function name - the actual regex would be much longer.. What characters are valid for JavaScript variable names?






          share|improve this answer


























          • sure if you can create a good regex to extract the string from the arrow function, that'd be useful.

            – Alexander Mills
            Nov 23 '18 at 0:13



















          1














          This is for a library, so I won't have any other information besides:



          const stew = {
          moo: () => foo.bar.star.guitar
          }


          so one thing I can do is:



          let guitar;
          try{
          guitar = stew.moo();
          }
          catch(err){
          console.error('Could not get value from:', stew.moo.toString());
          }


          aka, just log the string representation of the function. This is good enough information for the user to have to debug the problem.



          For a full demo see:
          https://gist.github.com/ORESoftware/5a1626037cb8ba568cdffa69374eac1d






          share|improve this answer

































            1














            based on your comments about this being for useful error messages, I believe you can get away with Error.captureStackTrace



            const er = {};
            Error.captureStackTrace(er);

            const foo = {
            bar: {
            star: {
            guitar: "geetar"
            }
            }
            };

            const a = foo.bar.nope.guitar;

            console.log(er.stack);


            which logs



            const a = foo.bar.nope.guitar;
            ^





            share|improve this answer































              1














              If you are able to control the root variables that people can refer to, you could wrap them in a Proxy object which tracks the property access all the way down, like so:



              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


              I am then throwing this resolved path as an error in this example, but you could do whatever you like with it.






              share|improve this answer
























              • this would work, but I want to log the full path, not just the point where it failed. Proxy objects are cool tho.

                – Alexander Mills
                Nov 23 '18 at 9:44











              • Not sure I get you - it does give the full path

                – Lauren
                Nov 23 '18 at 11:08











              • You have 3 console.log output lines, they arent showing the full path, only shows where it failed. For example if it failed at bar it would say could not resolve foo.bar

                – Alexander Mills
                Nov 23 '18 at 20:50








              • 1





                Ah yes I get you now! Hmm, needs more thought.

                – Lauren
                Nov 24 '18 at 0:48











              • Any new ideas on this front? thx. This answer is fine, just leave it.

                – Alexander Mills
                Nov 29 '18 at 21:17











              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53439136%2fget-string-representation-of-object-path%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              5 Answers
              5






              active

              oldest

              votes








              5 Answers
              5






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              1














              One approach could be to use a reducer to extract the value from a supplied path. For a path such as bar.star.guitar, you could extract the value geetar from object:



              const foo = {
              bar: {
              star: {
              guitar: 'geetar'
              }
              }
              }


              via the following:






              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)





              The idea here is to iterate in order through each "part" (ie string separated by '.') of the input path, and incrementally extract and return the value corresponding to the part (key) of the input object being processed. We incrementally continue this process until the end of the path is reached, at which point we arrive at the desired value (if it exists)






              share|improve this answer


























              • I don't understand this answer - I don't have 'foo.bar.star.guitar' as a string. I don't have that info. All I know is whether the object resolved or it threw an error "cannot read property x of undefined'.

                – Alexander Mills
                Nov 23 '18 at 0:10













              • @AlexanderMills right - so you have some arbitrary path string, and you need to extract the value corresponding to that path from input object? The snippet above is intended to illustrate how this can be done in general terms. Also, something to be aware of is that the path foo.bar.star.guitar is actually invalid for the object foo in your OP. Is there a format that you would prefer this answer to be presented in?

                – Dacre Denny
                Nov 23 '18 at 0:37






              • 1





                Your answer is how to resolve foo.bar.star.guitar from 'foo.bar.star.guitar'. But the question is about how to infer 'foo.bar.star.guitar' from foo.bar.star.guitar, for generating error messages for improper object access.

                – Lauren
                Nov 23 '18 at 7:34
















              1














              One approach could be to use a reducer to extract the value from a supplied path. For a path such as bar.star.guitar, you could extract the value geetar from object:



              const foo = {
              bar: {
              star: {
              guitar: 'geetar'
              }
              }
              }


              via the following:






              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)





              The idea here is to iterate in order through each "part" (ie string separated by '.') of the input path, and incrementally extract and return the value corresponding to the part (key) of the input object being processed. We incrementally continue this process until the end of the path is reached, at which point we arrive at the desired value (if it exists)






              share|improve this answer


























              • I don't understand this answer - I don't have 'foo.bar.star.guitar' as a string. I don't have that info. All I know is whether the object resolved or it threw an error "cannot read property x of undefined'.

                – Alexander Mills
                Nov 23 '18 at 0:10













              • @AlexanderMills right - so you have some arbitrary path string, and you need to extract the value corresponding to that path from input object? The snippet above is intended to illustrate how this can be done in general terms. Also, something to be aware of is that the path foo.bar.star.guitar is actually invalid for the object foo in your OP. Is there a format that you would prefer this answer to be presented in?

                – Dacre Denny
                Nov 23 '18 at 0:37






              • 1





                Your answer is how to resolve foo.bar.star.guitar from 'foo.bar.star.guitar'. But the question is about how to infer 'foo.bar.star.guitar' from foo.bar.star.guitar, for generating error messages for improper object access.

                – Lauren
                Nov 23 '18 at 7:34














              1












              1








              1







              One approach could be to use a reducer to extract the value from a supplied path. For a path such as bar.star.guitar, you could extract the value geetar from object:



              const foo = {
              bar: {
              star: {
              guitar: 'geetar'
              }
              }
              }


              via the following:






              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)





              The idea here is to iterate in order through each "part" (ie string separated by '.') of the input path, and incrementally extract and return the value corresponding to the part (key) of the input object being processed. We incrementally continue this process until the end of the path is reached, at which point we arrive at the desired value (if it exists)






              share|improve this answer















              One approach could be to use a reducer to extract the value from a supplied path. For a path such as bar.star.guitar, you could extract the value geetar from object:



              const foo = {
              bar: {
              star: {
              guitar: 'geetar'
              }
              }
              }


              via the following:






              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)





              The idea here is to iterate in order through each "part" (ie string separated by '.') of the input path, and incrementally extract and return the value corresponding to the part (key) of the input object being processed. We incrementally continue this process until the end of the path is reached, at which point we arrive at the desired value (if it exists)






              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)





              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)






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Nov 22 '18 at 23:58

























              answered Nov 22 '18 at 23:48









              Dacre DennyDacre Denny

              11.7k41031




              11.7k41031













              • I don't understand this answer - I don't have 'foo.bar.star.guitar' as a string. I don't have that info. All I know is whether the object resolved or it threw an error "cannot read property x of undefined'.

                – Alexander Mills
                Nov 23 '18 at 0:10













              • @AlexanderMills right - so you have some arbitrary path string, and you need to extract the value corresponding to that path from input object? The snippet above is intended to illustrate how this can be done in general terms. Also, something to be aware of is that the path foo.bar.star.guitar is actually invalid for the object foo in your OP. Is there a format that you would prefer this answer to be presented in?

                – Dacre Denny
                Nov 23 '18 at 0:37






              • 1





                Your answer is how to resolve foo.bar.star.guitar from 'foo.bar.star.guitar'. But the question is about how to infer 'foo.bar.star.guitar' from foo.bar.star.guitar, for generating error messages for improper object access.

                – Lauren
                Nov 23 '18 at 7:34



















              • I don't understand this answer - I don't have 'foo.bar.star.guitar' as a string. I don't have that info. All I know is whether the object resolved or it threw an error "cannot read property x of undefined'.

                – Alexander Mills
                Nov 23 '18 at 0:10













              • @AlexanderMills right - so you have some arbitrary path string, and you need to extract the value corresponding to that path from input object? The snippet above is intended to illustrate how this can be done in general terms. Also, something to be aware of is that the path foo.bar.star.guitar is actually invalid for the object foo in your OP. Is there a format that you would prefer this answer to be presented in?

                – Dacre Denny
                Nov 23 '18 at 0:37






              • 1





                Your answer is how to resolve foo.bar.star.guitar from 'foo.bar.star.guitar'. But the question is about how to infer 'foo.bar.star.guitar' from foo.bar.star.guitar, for generating error messages for improper object access.

                – Lauren
                Nov 23 '18 at 7:34

















              I don't understand this answer - I don't have 'foo.bar.star.guitar' as a string. I don't have that info. All I know is whether the object resolved or it threw an error "cannot read property x of undefined'.

              – Alexander Mills
              Nov 23 '18 at 0:10







              I don't understand this answer - I don't have 'foo.bar.star.guitar' as a string. I don't have that info. All I know is whether the object resolved or it threw an error "cannot read property x of undefined'.

              – Alexander Mills
              Nov 23 '18 at 0:10















              @AlexanderMills right - so you have some arbitrary path string, and you need to extract the value corresponding to that path from input object? The snippet above is intended to illustrate how this can be done in general terms. Also, something to be aware of is that the path foo.bar.star.guitar is actually invalid for the object foo in your OP. Is there a format that you would prefer this answer to be presented in?

              – Dacre Denny
              Nov 23 '18 at 0:37





              @AlexanderMills right - so you have some arbitrary path string, and you need to extract the value corresponding to that path from input object? The snippet above is intended to illustrate how this can be done in general terms. Also, something to be aware of is that the path foo.bar.star.guitar is actually invalid for the object foo in your OP. Is there a format that you would prefer this answer to be presented in?

              – Dacre Denny
              Nov 23 '18 at 0:37




              1




              1





              Your answer is how to resolve foo.bar.star.guitar from 'foo.bar.star.guitar'. But the question is about how to infer 'foo.bar.star.guitar' from foo.bar.star.guitar, for generating error messages for improper object access.

              – Lauren
              Nov 23 '18 at 7:34





              Your answer is how to resolve foo.bar.star.guitar from 'foo.bar.star.guitar'. But the question is about how to infer 'foo.bar.star.guitar' from foo.bar.star.guitar, for generating error messages for improper object access.

              – Lauren
              Nov 23 '18 at 7:34













              1














              const stew = {
              moo: () => foo.bar.star.guitar
              }

              stew.moo.toString().match(/([a-z0-9_$]+.?)+/)[0]
              // returns "foo.bar.star.guitar"


              This somewhat depends on people always using the same kind of function. Also I just used a short-hand for valid function name - the actual regex would be much longer.. What characters are valid for JavaScript variable names?






              share|improve this answer


























              • sure if you can create a good regex to extract the string from the arrow function, that'd be useful.

                – Alexander Mills
                Nov 23 '18 at 0:13
















              1














              const stew = {
              moo: () => foo.bar.star.guitar
              }

              stew.moo.toString().match(/([a-z0-9_$]+.?)+/)[0]
              // returns "foo.bar.star.guitar"


              This somewhat depends on people always using the same kind of function. Also I just used a short-hand for valid function name - the actual regex would be much longer.. What characters are valid for JavaScript variable names?






              share|improve this answer


























              • sure if you can create a good regex to extract the string from the arrow function, that'd be useful.

                – Alexander Mills
                Nov 23 '18 at 0:13














              1












              1








              1







              const stew = {
              moo: () => foo.bar.star.guitar
              }

              stew.moo.toString().match(/([a-z0-9_$]+.?)+/)[0]
              // returns "foo.bar.star.guitar"


              This somewhat depends on people always using the same kind of function. Also I just used a short-hand for valid function name - the actual regex would be much longer.. What characters are valid for JavaScript variable names?






              share|improve this answer















              const stew = {
              moo: () => foo.bar.star.guitar
              }

              stew.moo.toString().match(/([a-z0-9_$]+.?)+/)[0]
              // returns "foo.bar.star.guitar"


              This somewhat depends on people always using the same kind of function. Also I just used a short-hand for valid function name - the actual regex would be much longer.. What characters are valid for JavaScript variable names?







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Nov 23 '18 at 0:16

























              answered Nov 23 '18 at 0:13









              LaurenLauren

              1,2131129




              1,2131129













              • sure if you can create a good regex to extract the string from the arrow function, that'd be useful.

                – Alexander Mills
                Nov 23 '18 at 0:13



















              • sure if you can create a good regex to extract the string from the arrow function, that'd be useful.

                – Alexander Mills
                Nov 23 '18 at 0:13

















              sure if you can create a good regex to extract the string from the arrow function, that'd be useful.

              – Alexander Mills
              Nov 23 '18 at 0:13





              sure if you can create a good regex to extract the string from the arrow function, that'd be useful.

              – Alexander Mills
              Nov 23 '18 at 0:13











              1














              This is for a library, so I won't have any other information besides:



              const stew = {
              moo: () => foo.bar.star.guitar
              }


              so one thing I can do is:



              let guitar;
              try{
              guitar = stew.moo();
              }
              catch(err){
              console.error('Could not get value from:', stew.moo.toString());
              }


              aka, just log the string representation of the function. This is good enough information for the user to have to debug the problem.



              For a full demo see:
              https://gist.github.com/ORESoftware/5a1626037cb8ba568cdffa69374eac1d






              share|improve this answer






























                1














                This is for a library, so I won't have any other information besides:



                const stew = {
                moo: () => foo.bar.star.guitar
                }


                so one thing I can do is:



                let guitar;
                try{
                guitar = stew.moo();
                }
                catch(err){
                console.error('Could not get value from:', stew.moo.toString());
                }


                aka, just log the string representation of the function. This is good enough information for the user to have to debug the problem.



                For a full demo see:
                https://gist.github.com/ORESoftware/5a1626037cb8ba568cdffa69374eac1d






                share|improve this answer




























                  1












                  1








                  1







                  This is for a library, so I won't have any other information besides:



                  const stew = {
                  moo: () => foo.bar.star.guitar
                  }


                  so one thing I can do is:



                  let guitar;
                  try{
                  guitar = stew.moo();
                  }
                  catch(err){
                  console.error('Could not get value from:', stew.moo.toString());
                  }


                  aka, just log the string representation of the function. This is good enough information for the user to have to debug the problem.



                  For a full demo see:
                  https://gist.github.com/ORESoftware/5a1626037cb8ba568cdffa69374eac1d






                  share|improve this answer















                  This is for a library, so I won't have any other information besides:



                  const stew = {
                  moo: () => foo.bar.star.guitar
                  }


                  so one thing I can do is:



                  let guitar;
                  try{
                  guitar = stew.moo();
                  }
                  catch(err){
                  console.error('Could not get value from:', stew.moo.toString());
                  }


                  aka, just log the string representation of the function. This is good enough information for the user to have to debug the problem.



                  For a full demo see:
                  https://gist.github.com/ORESoftware/5a1626037cb8ba568cdffa69374eac1d







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 23 '18 at 0:24

























                  answered Nov 23 '18 at 0:10









                  Alexander MillsAlexander Mills

                  18.8k32154317




                  18.8k32154317























                      1














                      based on your comments about this being for useful error messages, I believe you can get away with Error.captureStackTrace



                      const er = {};
                      Error.captureStackTrace(er);

                      const foo = {
                      bar: {
                      star: {
                      guitar: "geetar"
                      }
                      }
                      };

                      const a = foo.bar.nope.guitar;

                      console.log(er.stack);


                      which logs



                      const a = foo.bar.nope.guitar;
                      ^





                      share|improve this answer




























                        1














                        based on your comments about this being for useful error messages, I believe you can get away with Error.captureStackTrace



                        const er = {};
                        Error.captureStackTrace(er);

                        const foo = {
                        bar: {
                        star: {
                        guitar: "geetar"
                        }
                        }
                        };

                        const a = foo.bar.nope.guitar;

                        console.log(er.stack);


                        which logs



                        const a = foo.bar.nope.guitar;
                        ^





                        share|improve this answer


























                          1












                          1








                          1







                          based on your comments about this being for useful error messages, I believe you can get away with Error.captureStackTrace



                          const er = {};
                          Error.captureStackTrace(er);

                          const foo = {
                          bar: {
                          star: {
                          guitar: "geetar"
                          }
                          }
                          };

                          const a = foo.bar.nope.guitar;

                          console.log(er.stack);


                          which logs



                          const a = foo.bar.nope.guitar;
                          ^





                          share|improve this answer













                          based on your comments about this being for useful error messages, I believe you can get away with Error.captureStackTrace



                          const er = {};
                          Error.captureStackTrace(er);

                          const foo = {
                          bar: {
                          star: {
                          guitar: "geetar"
                          }
                          }
                          };

                          const a = foo.bar.nope.guitar;

                          console.log(er.stack);


                          which logs



                          const a = foo.bar.nope.guitar;
                          ^






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 23 '18 at 0:38









                          rlemonrlemon

                          13.7k1077115




                          13.7k1077115























                              1














                              If you are able to control the root variables that people can refer to, you could wrap them in a Proxy object which tracks the property access all the way down, like so:



                              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


                              I am then throwing this resolved path as an error in this example, but you could do whatever you like with it.






                              share|improve this answer
























                              • this would work, but I want to log the full path, not just the point where it failed. Proxy objects are cool tho.

                                – Alexander Mills
                                Nov 23 '18 at 9:44











                              • Not sure I get you - it does give the full path

                                – Lauren
                                Nov 23 '18 at 11:08











                              • You have 3 console.log output lines, they arent showing the full path, only shows where it failed. For example if it failed at bar it would say could not resolve foo.bar

                                – Alexander Mills
                                Nov 23 '18 at 20:50








                              • 1





                                Ah yes I get you now! Hmm, needs more thought.

                                – Lauren
                                Nov 24 '18 at 0:48











                              • Any new ideas on this front? thx. This answer is fine, just leave it.

                                – Alexander Mills
                                Nov 29 '18 at 21:17
















                              1














                              If you are able to control the root variables that people can refer to, you could wrap them in a Proxy object which tracks the property access all the way down, like so:



                              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


                              I am then throwing this resolved path as an error in this example, but you could do whatever you like with it.






                              share|improve this answer
























                              • this would work, but I want to log the full path, not just the point where it failed. Proxy objects are cool tho.

                                – Alexander Mills
                                Nov 23 '18 at 9:44











                              • Not sure I get you - it does give the full path

                                – Lauren
                                Nov 23 '18 at 11:08











                              • You have 3 console.log output lines, they arent showing the full path, only shows where it failed. For example if it failed at bar it would say could not resolve foo.bar

                                – Alexander Mills
                                Nov 23 '18 at 20:50








                              • 1





                                Ah yes I get you now! Hmm, needs more thought.

                                – Lauren
                                Nov 24 '18 at 0:48











                              • Any new ideas on this front? thx. This answer is fine, just leave it.

                                – Alexander Mills
                                Nov 29 '18 at 21:17














                              1












                              1








                              1







                              If you are able to control the root variables that people can refer to, you could wrap them in a Proxy object which tracks the property access all the way down, like so:



                              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


                              I am then throwing this resolved path as an error in this example, but you could do whatever you like with it.






                              share|improve this answer













                              If you are able to control the root variables that people can refer to, you could wrap them in a Proxy object which tracks the property access all the way down, like so:



                              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


                              I am then throwing this resolved path as an error in this example, but you could do whatever you like with it.







                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Nov 23 '18 at 7:49









                              LaurenLauren

                              1,2131129




                              1,2131129













                              • this would work, but I want to log the full path, not just the point where it failed. Proxy objects are cool tho.

                                – Alexander Mills
                                Nov 23 '18 at 9:44











                              • Not sure I get you - it does give the full path

                                – Lauren
                                Nov 23 '18 at 11:08











                              • You have 3 console.log output lines, they arent showing the full path, only shows where it failed. For example if it failed at bar it would say could not resolve foo.bar

                                – Alexander Mills
                                Nov 23 '18 at 20:50








                              • 1





                                Ah yes I get you now! Hmm, needs more thought.

                                – Lauren
                                Nov 24 '18 at 0:48











                              • Any new ideas on this front? thx. This answer is fine, just leave it.

                                – Alexander Mills
                                Nov 29 '18 at 21:17



















                              • this would work, but I want to log the full path, not just the point where it failed. Proxy objects are cool tho.

                                – Alexander Mills
                                Nov 23 '18 at 9:44











                              • Not sure I get you - it does give the full path

                                – Lauren
                                Nov 23 '18 at 11:08











                              • You have 3 console.log output lines, they arent showing the full path, only shows where it failed. For example if it failed at bar it would say could not resolve foo.bar

                                – Alexander Mills
                                Nov 23 '18 at 20:50








                              • 1





                                Ah yes I get you now! Hmm, needs more thought.

                                – Lauren
                                Nov 24 '18 at 0:48











                              • Any new ideas on this front? thx. This answer is fine, just leave it.

                                – Alexander Mills
                                Nov 29 '18 at 21:17

















                              this would work, but I want to log the full path, not just the point where it failed. Proxy objects are cool tho.

                              – Alexander Mills
                              Nov 23 '18 at 9:44





                              this would work, but I want to log the full path, not just the point where it failed. Proxy objects are cool tho.

                              – Alexander Mills
                              Nov 23 '18 at 9:44













                              Not sure I get you - it does give the full path

                              – Lauren
                              Nov 23 '18 at 11:08





                              Not sure I get you - it does give the full path

                              – Lauren
                              Nov 23 '18 at 11:08













                              You have 3 console.log output lines, they arent showing the full path, only shows where it failed. For example if it failed at bar it would say could not resolve foo.bar

                              – Alexander Mills
                              Nov 23 '18 at 20:50







                              You have 3 console.log output lines, they arent showing the full path, only shows where it failed. For example if it failed at bar it would say could not resolve foo.bar

                              – Alexander Mills
                              Nov 23 '18 at 20:50






                              1




                              1





                              Ah yes I get you now! Hmm, needs more thought.

                              – Lauren
                              Nov 24 '18 at 0:48





                              Ah yes I get you now! Hmm, needs more thought.

                              – Lauren
                              Nov 24 '18 at 0:48













                              Any new ideas on this front? thx. This answer is fine, just leave it.

                              – Alexander Mills
                              Nov 29 '18 at 21:17





                              Any new ideas on this front? thx. This answer is fine, just leave it.

                              – Alexander Mills
                              Nov 29 '18 at 21:17


















                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53439136%2fget-string-representation-of-object-path%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Wiesbaden

                              Marschland

                              Dieringhausen