3

I'm currently building a bigger object and need to get faster and more specific with debugging/inspecting values/results/returns.

Now I thought about the following:

var myObject = {
    whatever: null,
    whereever: null,
    debug: false,

    someFunction: function( arg ) {
        // General - would output *all* logs for all object functions.
        // if ( true === myObject.debug )
        //  console.log( 'FunctionNameHere', arg );

        // More specific - would output *only* the log for the currently targeted function
        if ( 'FunctionName' === myObject.debug )
            console.log( 'FunctionNameHere', arg );
    },
};

This would allow me to simply define the object var debug as one function name and only log this part.

The only problem is: How would I obtain the FunctionName/someFunction?

Sidenotes:

  • console.log( arguments.callee ); gives me the whole function source.
  • console.log( arguments.callee.name ); returns empty.
  • console.log( arguments.callee.toString() ); returns empty
  • console.log( arguments.caller ); returns undefined

If I take a look into the log of the whole object, I see prototype.name="Empty" and such. So no chance to get it directly out of the object.

Thanks!

7
  • So generally speaking - if debug is true then you want to log console a message with function name + arguments when any of myObject functions is executed? Commented Dec 13, 2011 at 18:18
  • @dzejkej Not exactly. If I set debug to the function name, then only the log of the equally named fn should trigger. This would allow me to build debug into each function and only trigger it, when needed/specified. Commented Dec 13, 2011 at 18:20
  • My answer contains a code that suits your requirements without any hardcoding. It is a bit too advanced, but hopefully it will motivate you to study this interesting language :P. Commented Dec 13, 2011 at 18:36
  • 1
    I read that you are just starting with JS and realized that this might be advanced for somebody new. I hope I didn't offend you :). That var x = y, a = b; is same as var x = y; var a = b; which is same as var x, a; x = y; a = b;. Just variable declaration and assignment. And JS is definitely interesting ;). Commented Dec 14, 2011 at 0:29
  • 1
    JS is small yet flexible and most of the meat is in libraries. Profiling - here are some links for Chrome and Firefox. Here is great video about Chrome newer goodies. Commented Dec 14, 2011 at 2:08

3 Answers 3

3

If you want to log every function if debug is true and if debug is set to the name of function, then log only that function you don't have to hardcode this into every single function of yours.

What you can do is dynamically rewrite the function. It is bit of a magic, but it is lot more flexible and you don't have to change anything when you add more functions or change their names.

HERE is the working code.

for (var key in myObject) {
  // if the keys belongs to object and it is a function
  if (myObject.hasOwnProperty(key) && (typeof myObject[key] === 'function')) {
    // overwrite this function
    myObject[key] = (function() {
      // save the previous function
      var functionName = key, functionCode = myObject[functionName];
      // return new function that will write log message and run the saved function
      return function() {
        if (myObject.debug === true || myObject.debug === functionName) {
          console.log('I am function ' + functionName, ' with arguments: ', arguments);
        }
        functionCode(arguments);
      };
    })();
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for that function. The problem (I guess) is that my object works with google.maps, so this breaks everything, as latlng break in the middle...
Ok, got it working inside the object. Thanks - marked as solution.
1

It is an anonymous function it doesn't have a name and thus you can't get to it as it is right now.

If you had declared it like this:

someFunction: function iNowHaveAName( arg )

You would be able to get at the name in different ways depending on the browser you are in.

In browsers that supports it, you can use arguments.callee.name. (this is fast and performance wise free)

In browsers that doesn't you can catch an exception and find it in the stacktrace:

try {
 i.dont.exist+=1;
}
catch(e) {
//play with the stacktrace here
}

This is slow and performance wise expensive - don't do it in production code :)

3 Comments

Note that arguments.callee is deprecated, and will be removed in future versions of JavaScript. It's already not available in ES5 strict mode.
I'm just starting with JS, so I didn't know that I can name them like this: someFunction: function iNowHaveAName. Thanks +1
Also, there's a better way of getting the name than the backtrace: function getName(f){ var match = /function (\w+)/.exec(f+""); return match && match[1]; }
1

If a function does not have a name, you cannot get it. An anonymous function—which is exactly what you have—does not have a name. Assigning one or more variables or object properties to reference the function value does not give it a name.

Consider these examples:

var a = [function(){}];
var b = a;
var c = a[0];

What is the "name" of that single function? a[0]? b[0]? c? Why should one be chosen over the other?

JavaScript does not have any method allowing you to ask for all reference to a particular object (including functions).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.