I'm developing a javascript application that consists of many objects and functions (object methods). I want to be able to log many events in the life cycle of the application. My problem is that inside the logger I want to know which function invoked the log entry, so I can save that data along with the log message. This means that every function needs to somehow be able to reference itself, so I can pass that reference to the logger.
I'm using javascript strict mode, so using arguments.callee
inside the function is not allowed.
Here's a very simplified code sample you can run. I'm just using here alert
instead of my logger for simplicity.
(function(){
"use strict";
window.myObject = {
id : 'myObject',
myFunc : function(){
alert(this.id); // myObject
alert(this.myFunc.id); // myFunc - I don't want to do this. I want something generic for all functions under any object
alert('???') // myFunc
alert(arguments.callee.id); // Will throw an error because arguments.callee in not allowed in strict mode
}
}
myObject.myFunc.id = 'myFunc';
myObject.myFunc();
})();
this
related to myObject
and not to myFunc
"use stict";
. I want to keep strict mode since it provides better performance, and constitutes good coding practice.Any input will be appreciated.
If you're not familiar with "strict mode", this is a good place read about it: JavaScript Strict Mode
Here's a very hacky way of doing it:
(function(){
"use strict";
window.myObject = {
id: 'myObject',
myFunc: function () {
// need this if to circumvent 'use strict' since funcId doesn't exist yet
if (typeof funcId != 'undefined')
alert(funcId);
},
myFunc2: function () {
// need this if to circumvent 'use strict' since funcId doesn't exist yet
if (typeof funcId != 'undefined')
alert(funcId);
}
}
// We're going to programatically find the name of each function and 'inject' that name
// as the variable 'funcId' into each function by re-writing that function in a wrapper
for (var i in window.myObject) {
var func = window.myObject[i];
if (typeof func === 'function') {
window.myObject[i] = Function('var funcId = "' + i + '"; return (' + window.myObject[i] + ')()');
}
}
window.myObject.myFunc();
window.myObject.myFunc2();
})();
Essentially, we are circumventing the 'use strict' declaration by recompiling each function from a string after we've found out that function's name. To do this, we create a wrapper around each function that declares a string variable 'funcId' equal to our target function's name, so that the variable is now exposed to the function within through closure.
Eh, not the best way to do things, but it works. Alternatively, you can simply call a non-strict function from within:
(function(){
"use strict";
window.myObject = {
id: 'myObject',
myFunc: function () {
alert(getFuncName())
},
myFunc2: function () {
alert(getFuncName());
}
}
})();
// non-strict function here
function getFuncName(){
return arguments.callee.caller.id; // Just fyi, IE doesn't have id var I think...so you gotta parse toString or something
}
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With