JavaScript: Get function name inside of itself - javascript

Yes, I realize there are countless threads out there about this issue, for starters:
Get function name from function itself [duplicate]
Get function name from inside itself
Arguments.callee is deprecated - what should be used instead?
But the problem with the answers given is arguments.callee is deprecated. All of the answers say to just give your function a name. However, from what I can tell, that does not fix my problem. Say I have the following function:
function blah() {
// arguments.callee.name is deprecated
console.log('The function name is: ' + arguments.callee.name + '.');
}
But because that's deprecated, I shouldn't be using it, so what should I be using instead? Is there any way I can access the function name when inside the function itself, or am I just out of probability here?
If it makes things easier, I am using the framework Ext JS, but I haven't found a way of knowing the function's name. If not, is there a jQuery approach? I'm desperate here.

You can provoke an exception and examine the stack trace.
The following proof of context works in the Chrome browser:
function test () {
try { [].undef () } catch (e) {
console.log (e.stack.split ('\n')[1].split (/\s+/)[2]);
}
}
For a more robust implementation consult http://www.eriwen.com/javascript/js-stack-trace/
which provides a full stack trace in any browser.
A more modern and comprehensive stack trace analyzer is http://stacktracejs.com

With some poking around, I came up with this SO thread, so building on top of that, I made a very very hacky solution that works (in both Chrome and FF... not sure about IE, but I doubt it works). Warning: this is very specific to my own use, so your mileage will definitely vary. Anyway, this is my code:
getLogLocation: function() {
var ua = navigator.userAgent;
var isFF = ua.search(/firefox/i) !== -1 ? true : false;
var isChrome = ua.search(/chrome/i) !== -1 ? true : false;
if (isFF || isChrome) {
var stack = Error().stack,
cname = '',
funcPattern,
classPattern = /.*\/(.*)\.js/; // looking for something between the last backslash and .js
if (stack) {
var stacks = stack.split('\n');
if (stacks) {
var theStack;
// the browsers create the stack string differently
if (isChrome) {
// the stack has getClassName, then logMessage, then our calling class, but Chrome has some added garbage
theStack = stacks[4];
funcPattern = /.*\.(.*)\s+\(/; // looking for something between a period and the first paren
}
else {
theStack = stacks[2];
funcPattern = /^\.*(.*)\#/; // looking for something between a period and an # symbol
}
var matches = theStack.match(classPattern);
cname = matches[1] + '::';
matches = theStack.match(funcPattern);
cname += matches[1] + ':';
}
}
return cname;
}
}
And if you're curious what my stack looks like, here're the relevant lines:
Firefox (cut out a lot of lines)
".getClassName#http://127.0.0.1/javascripts/app/mixins/ConsoleMixin.js?_dc=1383836090216:72
.logMessage#http://127.0.0.1/javascripts/app/mixins/ConsoleMixin.js?_dc=1383836090216:31
.constructor#http://127.0.0.1/javascripts/app/BaseController.js?_dc=1383836089659:39
..."
Chrome (the first 2 lines are the garbage I have to accommodate for... after that, it's similar to FF's Stack string)
"Error
at Error (<anonymous>)
at Ext.define.getLogLocation (http://127.0.0.1/javascripts/app/mixins/ConsoleMixin.js?_dc=1383836606405:72:19)
at Ext.define.logMessage (http://127.0.0.1/javascripts/app/mixins/ConsoleMixin.js?_dc=1383836606405:31:24)
at new Ext.define.constructor (http://127.0.0.1/javascripts/app/BaseController.js?_dc=1383836606265:39:14)
..."
See this jsFiddle for a working example... had to change the stack values because we're no longer in Ext JS.
Now, a little explanation. getLogLocation resides as a function in an Ext JS class (ConsoleMixin), and another function inside of ConsoleMixin (logMessage) calls getLogLocation, and logMessage is called by our outer class's function (constructor), which is why I have to compensate for the first 2 stack values. Like I said, very hacky and specific to my need, but hopefully someone can make use of it.

Related

How to bind console.log to another function call so I can see line number of the script in console where it is called?

My code works but with additional parenthesis like myfunction()();. It should execute with single parenthesis just like normal e.g myfunction();.
I'm building console.time(); console.timeEnd(); polyfill for browsers (e.g <IE10) which do not have native built-in. Note: I have bind() polyfill in-case you think <IE10 does not have it.
Here is my code in "polyfill.js file".
(function() {
'use strict';
var console=window.console, timers={};
if (!console.time) {
console.time = function(name) {
var datenow = Date.now();
name = name? name: 'default';
if (timers[name]) {
console.warn('Timer "'+name+'" already exists.');
}
else timers[name] = datenow;
};
console.timeEnd = function(name) {
var datenow = Date.now();
name = name? name: 'default';
if (!timers[name]) {
console.warn('Timer "'+name+'" does not exists.');
}
else {
var endt = datenow - timers[name];
delete timers[name];
//below is the line where some changes are needed, But I don't know how.
return window.console.log.bind(window.console, name+ ': ' +endt+ 'ms');
}
};
}
}());
Now in another file "main.js file", when I use console.time(); console.timeEnd();, it should log code-line-number of this file in browser console (not the line-number of polyfill.js file). Of-course it works but notice additional parenthesis "()()" below which is not cool.
console.time();
//any code for performance test goes here.
console.timeEnd()(); //Note here "()()". It should be single "()"
I have consulted these 2 stackoverflow questions, but couldn't come up with the right answer.
Wrapping a wrapper of console log with correct file/line number?
A proper wrapper for console.log with correct line number?
I also checked new Error().stack; as an option, but it is also not supported in those browser for which I'm building my polyfill.
Note: If anyone can suggest a solution with eval();, you can. It is also acceptable for me.
There is in fact a function for that called console.trace, which you can read more about in the MDN page.
What it does is print the entire stack trace to the line where it has been called from.
So, for example, running the next code:
function firstFunc() {
secondFunc();
}
function secondFunc() {
console.trace('I was called here!');
}
console.log('Calling firstFunc:');
firstFunc();
will print out this output in the console:
Calling firstFunc:
I was called here!
secondFunc # VM141:6
firstFunc # VM141:2
(anonymous) # VM141:10 // Internal browser trace
Notice that in the given output, all functions are being called and defined in the Chrome console, hence the # VM141:. Generally, it prints the file instead of VM. So, had it been located in an index.js file, it would look like this:
Calling firstFunc:
I was called here!
secondFunc # index.js:8
Compatibility Note
The above method works for any sane browser, and IE11+. That is due to the implementation of console.trace only in IE11.
However, per OP's request, I can think of a creative way to support IE10, and that is by using the Error.prototype.stack property.
Now, of course, as MDN itself mentions it, it's a non-standard feature that should not be used in production, but neither is supporting IE6.
By creating an Error instance and then printing its stack, you can achieve a similar result.
const sumWithTrace = (num1, num2) => {
console.log(new Error().stack); // Creating a new error for its stack property
return num1 + num2;
};
sumWithTrace(1, 5); // returns 6 and prints trace in console

How to disable console.log messages based on criteria from specific javascript source (method, file) or message contents

I am working on project that uses quite a few js libraries and one of them is outputting awful lot into console, it is polluting the airwaves so bad that it makes it hard to debug....
I know how to disable logging completely by overriding console.log with this,
(function (original) {
console.enableLogging = function () {
console.log = original;
};
console.disableLogging = function () {
console.log = function () {};
};
})(console.log);
but how do it do that per source(file/url) of where message originated?
Preamble
The beginning discusses how stuff works in general. If you just care for the code, skip Introduction and scroll to the Solution heading.
Introduction
Problem:
there is a lot of console noise in a web application. A significant amount of that noise is coming from third party code which we do not have access to. Some of the log noise might be coming from our code, as well.
Requirement:
reduce the noise by stopping the log. Some logs should still be kept and the decision about those should be decoupled from the code that is doing the logging. The granularity needed is "per-file". We should be able to choose which files do or do not add log messages. Finally, this will not be used in production code.
Assumption: this will be ran in a developer controlled browser. In that case, I will not focus on backwards compatibility.
Prior work:
First off logging can be enabled/disabled globally using this
(function (original) {
console.enableLogging = function () {
console.log = original;
};
console.disableLogging = function () {
console.log = function () {};
};
})(console.log);
(code posted in the question but also here for reference)
However, that does not allow for any granularity.
This could be modified to work on only specific modules but that cannot be done for third party code.
A mixed approach would be to disable logging globally but enable it in each of our modules. Problem there is that we have to modify each of our files and we will not get some potentially useful external messages.
A logging framework can be used but it might be an overkill. Although, to be honest, that's what I'd go for, I think, but it may need some integration into the product.
So, we need something light-weight-ish that has some configuration and does not need to be pretty.
Proposal:
The Loginator (title subject to change)
Let's start with the basics - we already know we can override the global log function. We'll take that and work with it. But first, let's recognise that the console object supports more than just .log. There could be various logging functions used. So-o-o, let's disable all of them.
Silence everything
//shorthand for further code.
function noop() {}
const savedFunctions = Object.keys(console)
.reduce((memo, key) => {
if(typeof console[key] == "function") {
//keep a copy just in case we need it
memo[key] = console[key];
//de-fang any functions
console[key] = noop;
}
return memo;
},
{});
console.log("Hello?");
console.info("Hello-o-o-o?");
console.warn("Can anybody hear me?");
console.error("I guess there is nobody there...");
savedFunctions.log("MUAHAHAHA!")
This can obviously be improved but it showcases how any and ll logging can be stopped. In reality, console.error should probably be left and console.warn might be also useful. But this is not the be-all-and-end-all solution.
Next, since we can override console functionality...why not supply our own?
Custom logging
const originalLog = console.log;
console.log = function selectiveHearing() {
if (arguments[0].indexOf("die") !== -1) {
arguments[0] = "Have a nice day!";
}
return originalLog.apply(console, arguments)
}
console.log("Hello.");
console.log("My name is Inigo Montoya.");
console.log("You killed my father.");
console.log("Prepare to die.");
That is all the tools we need to roll our own mini-logging framework.
How to do selective logging
The only thing missing is to determine which file something is coming from. We just need a stack trace.
// The magic
console.log(new Error().stack);
/* SAMPLE:
Error
at Object.module.exports.request (/home/vagrant/src/kumascript/lib/kumascript/caching.js:366:17)
at attempt (/home/vagrant/src/kumascript/lib/kumascript/loaders.js:180:24)
at ks_utils.Class.get (/home/vagrant/src/kumascript/lib/kumascript/loaders.js:194:9)
at /home/vagrant/src/kumascript/lib/kumascript/macros.js:282:24
at /home/vagrant/src/kumascript/node_modules/async/lib/async.js:118:13
at Array.forEach (native)
at _each (/home/vagrant/src/kumascript/node_modules/async/lib/async.js:39:24)
at Object.async.each (/home/vagrant/src/kumascript/node_modules/async/lib/async.js:117:9)
at ks_utils.Class.reloadTemplates (/home/vagrant/src/kumascript/lib/kumascript/macros.js:281:19)
at ks_utils.Class.process (/home/vagrant/src/kumascript/lib/kumascript/macros.js:217:15)
*/
(Relevant bit copied here.)
True, there are some better ways to do it but not a lot. It would either require a framework or it's browser specific - error stacks are not officially supported but they work in Chrome, Edge, and Firefox. Also, come on - it's literally one line - we want simple and don't mind dirty, so I'm happy for the tradeoff.
Solution
Putting it all together. Warning: Do NOT use this in production
(function(whitelist = [], functionsToPreserve = ["error"]) {
function noop() {}
//ensure we KNOW that there is a log function here, just in case
const savedFunctions = { log: console.log }
//proceed with nuking the rest of the chattiness away
Object.keys(console)
.reduce((memo, key) => {
if(typeof console[key] == "function" && functionsToPreserve.indexOf(key) != -1 ) {
memo[key] = console[key];
console[key] = noop;
}
return memo;
},
savedFunctions); //<- it's a const so we can't re-assign it. Besides, we don't need to, if we use it as a seed for reduce()
console.log = function customLog() {
//index 0 - the error message
//index 1 - this function
//index 2 - the calling function, i.e., the actual one that did console.log()
const callingFile = new Error().stack.split("\n")[2];
if (whitelist.some(entry => callingFile.includes(entry))) {
savedFunctions.log.apply(console, arguments)
}
}
})(["myFile.js"]) //hey, it's SOMEWHAT configurable
Or a blacklist
(function(blacklist = [], functionsToPreserve = ["error"]) {
function noop() {}
//ensure we KNOW that there is a log function here, just in case
const savedFunctions = {
log: console.log
}
//proceed with nuking the rest of the chattiness away
Object.keys(console)
.reduce((memo, key) => {
if (typeof console[key] == "function" && functionsToPreserve.indexOf(key) != -1) {
memo[key] = console[key];
console[key] = noop;
}
return memo;
},
savedFunctions); //<- it's a const so we can't re-assign it. Besides, we don't need to, if we use it as a seed for reduce()
console.log = function customLog() {
//index 0 - the error message
//index 1 - this function
//index 2 - the calling function, i.e., the actual one that did console.log()
const callingFile = new Error().stack.split("\n")[2];
if (blacklist.some(entry => callingFile.includes(entry))) {
return;
} else {
savedFunctions.log.apply(console, arguments);
}
}
})(["myFile.js"])
So, this is a custom logger. Sure, it's not perfect but it will do the job. And, hey, since the whitelisting is a bit loose, it could be turned to an advantage:
to whitelist a bunch of files that share a substring, say, all myApp can include myApp1.js, myApp2.js, and myApp3.js.
although if you want specific files, you can just pass the full name, including extension. I doubt there would be a bunch of duplicate filenames.
finally, the stack trace will include the name of the calling function, if any, so you can actually just pass that and that will whitelist on per-function basis. However, it relies on the function having a name and it's more likely for function names to clash, so use with care
Other than that, there can certainly be improvements but that is the basis of it. The info/warn methods can also be overriden, for example.
So, this, if used, should only be in dev builds. There are a lot of ways to make it not go into production, so I won't discuss them but here is one thing I can mention: you can also use this anywhere if you save it as a bookmarklet
javascript:!function(){function c(){}var a=arguments.length<=0||void 0===arguments[0]?[]:arguments[0],b=arguments.length<=1||void 0===arguments[1]?["error"]:arguments[1],d={log:console.log};Object.keys(console).reduce(function(a,d){return"function"==typeof console[d]&&b.indexOf(d)!=-1&&(a[d]=console[d],console[d]=c),a},d),console.log=function(){var c=(new Error).stack.split("\n")[2];a.some(function(a){return c.includes(a)})&&d.log.apply(console,arguments)}}(["myFile.js"]);
This is it minified (although I passed it through Babel first, to use ES5 minification) and still configurable, to an extent, as you can change the very end where you can pass the whitelist. But other than that, it will work the same and is completely decoupled from the codebase. It will not run at pageload but if that's needed you can either use this as a userscript (still decoupled) or include it before other JS files in dev/debug builds only.
A note here - this will work in Chrome, Edge and Firefox. It's all the latest browsers, so I assume a developer will use at least one of them. The question is tagged as Chrome but I decided to widen the support. A Chrome only solution could work slightly better but it's not really a big loss of functionality.
I was as troubled as you. This is my approach. https://github.com/jchnxu/guard-with-debug
Simple usage:
localStorage.debug = [
'enable/console/log/in/this/file.ts',
'enable/console/log/in/this/folder/*',
'-disable/console/log/in/this/file.ts',
'-disable/console/log/in/this/folder/*',
// enable all
'*',
].join(',');
The benefit: it's zero-runtime.
Disclaimer: I am the author of this tiny utility
It work in chrome:
...index.html
<html>
<body>
<script>
(function(){
var original = console.log;
console.log = function(){
var script = document.currentScript;
alert(script.src);
if(script.src === 'file:///C:/Users/degr/Desktop/script.js') {
original.apply(console, arguments)
}
}
})();
console.log('this will be hidden');
</script>
<script src="script.js"></script>
</body>
</html>
...script.js
console.log('this will work');
Console.log does not work from index.html, but work from script.js. Both files situated on my desctop.
I've found these settings in the latest (July 2020) Chrome DevTools console to be helpful:
DevTools | Console | (sidebar icon) | user messages
DevTools | Console | (gear icon) | Select context only
DevTools | Console | (gear icon) | Hide network
I like (1) most, I only see the messages from "my" code. (2) hides messages from my iframe.
If it's an option to modify file, you can set a flag at top of file for disabling logs for that:
var DEBUG = false;
DEBUG && console.log("cyberpunk 2077");
To disable logs for all js files, put it once at top of any js file:
var DEBUG = false;
if (!DEBUG) {
console.log = () => {};
}
This is not pretty but will work.
Put something like this in your file before the <script> tag of the "bad" library :
<script>function GetFile(JSFile) {
var MReq = new XMLHttpRequest();
MReq.open('GET', JSFile, false);
MReq.send();
eval(MReq.responseText.replace(/console.log\(/g,"(function(){})("));
}</script>
Then replace the tag
<script src="badLib.js">
With:
GetFile("badLib.js")
Only for short time debugging.

angularjs $log - show line number

I use angularjs $log in chrome, but it shows the line like: angular.js:9037. I want to show the line number where I call this method. (Show my js name and the correct line). Does anyone know how to do it? Angular doesn't have this feature.
In Chrome there is a feature called Blackboxing.
You can use it to exclude / bypass (library) sources from your debug sessions or development workflow.
So if you blackbox angular the internals of the $log service get bypassed and the console prints the correct line number!
https://developer.chrome.com/devtools/docs/blackboxing
You can access it by applying a decorator to the $log service:
module.config(function logConfig($provide, $logProvider) {
$provide.decorator('$log', function ($delegate) {
var originalFns = {};
// Store the original log functions
angular.forEach($delegate, function (originalFunction, functionName) {
originalFns[functionName] = originalFunction;
});
var functionsToDecorate = ['debug', 'warn'];
// Apply the decorations
angular.forEach(functionsToDecorate, function (functionName) {
$delegate[functionName] = logDecorator(originalFns[functionName]);
});
return $delegate;
});
function logDecorator(fn) {
return function () {
var args = [].slice.call(arguments);
// Insert a separator between the existing log message(s) and what we're adding.
args.push(' - ');
// Use (instance of Error)'s stack to get the current line.
var stack = (new Error()).stack.split('\n').slice(1);
// Throw away the first item because it is the `$log.fn()` function,
// but we want the code that called `$log.fn()`.
stack.shift();
// We only want the top line, thanks.
stack = stack.slice(1, 2);
// Put it on the args stack.
args.push(stack);
// Call the original function with the new args.
fn.apply(fn, args);
};
}
});
I do this as an includable module, but I believe it could be done within the app's .config() as well.
I built this (along with some additional logic) by gluing together a number of different sources online; I'm usually really good at keeping references to them, but I guess I didn't when I built this, so unfortunately I can't reference my inspiration. If someone replies with it, I'll put it in here.
NOTE 1:
this is a slightly stripped-down version of what I actually use, so you'll have to double-check the logDecorator()s stack
pushy-shifty magic, though it should work as presented.
NOTE B:
MDN says that Error.prototype.stack is non-standard (requires IE10 and may not be supported on many mobile browsers) so you might want to look at augmenting this with something like stacktracejs to get the stack itself.
I have combined a couple of solutions from this page, as well others to build a simple demo in JSFiddle - to demonstrate use of $log service, enhancing it with decorators to add line number (line number from where $log call was made). I have also made a slightly more comprehensive solution in Plunker, demonstrating the use of $log service, enhancing it with decorators to add line number, caller file name and instance name. Hopefully, this will be useful to others.
JSFiddle URL - https://jsfiddle.net/abhatia/6qnz0frh/
This fiddle has been tested with following browsers:
IE 11 - (JSFiddle Javascript's first line's number is 72).
Firefox 46.0.1 - (JSFiddle Javascript's first line's number is 72).
Chrome 50.0.2661.94 m - (JSFiddle Javscript's first line's number is 71).
The results are good. But, please note that line number in Chrome will be off by 1, when compared to FF or IE, i.e. because JSFiddle's javascript's code first line number differs between FF/IE and Chrome, as listed above.
Plunker URL - https://embed.plnkr.co/YcfJ7V/
This plunk demonstrates the concept really well, with detailed explanation and also provides the console output with Angular's official example of default $log service, so the two could be contrasted. Plunk has also been tested with browsers listed above.
Below screenshot is the console output from the Plunk example above. There are 3 highlighted areas:
Red box shows console output using default $log service. $log functions invoked from controller.
Blue box shows console output using extended $log service. $log functions invoked from controller. You can see how the script name and line numbers are shown, as well as the controller name (used when instantiating $log).
Orange box contrasts console output from default and extend $log services.
This will become very clear when you review the Plunk code.
Here is the getLineNumber function used in JSFiddle (slightly enhanced version is used Plunker example to return caller file name):
function getLineNumber(newErr, sliceIndex1, sliceIndex2)
{
var lineNumber = -1;
var lineLocation;
var stack = newErr.stack.split('\n').slice(2);
if (navigator.userAgent.indexOf("Chrome") > -1) {
stack.shift();
}
stack = stack.slice(sliceIndex1, sliceIndex2);
var stackInString = stack + '';
var splitStack;
if (navigator.userAgent.indexOf("Chrome") > -1) {
splitStack = stackInString.split(" ");
}
else {
splitStack = stackInString.split("#");
}
lineLocation = splitStack[splitStack.length - 1];
//console.log(lineLocation);
lineNumber = lineLocation.split(":")[2];
return lineNumber;
}
The line number comes from the runtime. You can not set it in general case.
But not all is lost. In places where the line number is really important you can use a different call.
Remember to inject the $window and then:
$window.console.log("test1");
You loose some things this way like formatting, cross browsers filler code etc, but you do get line numbers correct for free without any per runtime specific code to do so.
Close to floatingLomas's answer
module.config(function($logProvider, $provide){
$provide.decorator('$log', function ($delegate) {
$delegate.info = function () {
var args = [].slice.call(arguments);
if (window.console && window.console.table)
console.trace(args[0], args[1]);
else
$delegate.log(null, args)
};
return $delegate;
});
})
Usually second # line is what you need, in this case 90618
I have used floatingLomas solution with some tweaks as it does not quite work on FF, the stack is slightly different. And phantomjs like IE does not support Error.stack and blows up.
The log location is clickable in chrome but not in ff.
app.config(function logConfig($provide, $logProvider) {
$provide.decorator('$log', function ($delegate) {
var originalFns = {};
// Store the original log functions
angular.forEach($delegate, function (originalFunction, functionName) {
originalFns[functionName] = originalFunction;
});
var functionsToDecorate = ['debug', 'warn'];
// Apply the decorations
angular.forEach(functionsToDecorate, function (functionName) {
$delegate[functionName] = logDecorator(originalFns[functionName]);
});
return $delegate;
});
function logDecorator(fn) {
return function () {
var args = [].slice.call(arguments);
// Insert a separator between the existing log message(s) and what we're adding.
args.push(' - ');
// Use (instance of Error)'s stack to get the current line.
var newErr = new Error();
// phantomjs does not support Error.stack and falls over so we will skip it
if (typeof newErr.stack !== 'undefined') {
var stack = newErr.stack.split('\n').slice(1);
if (navigator.userAgent.indexOf("Chrome") > -1) {
stack.shift();
}
stack = stack.slice(0, 1);
var stackInString = stack + '';
var splitStack;
if (navigator.userAgent.indexOf("Chrome") > -1) {
splitStack = stackInString.split(" ");
} else {
splitStack = stackInString.split("#");
}
var lineLocation = splitStack[splitStack.length - 1];
// Put it on the args stack.
args.push(lineLocation);
// Call the original function with the new args.
fn.apply(fn, args);
}
};
}
I use chrome version 65.0.3325.181
in my case,
go to menu, settings -> blackboxing
check blackbox content scripts
add blockbox pattern angular.js

Making a basic functions fails

Okay, thanks for the help I already got. Stupid spelling mistake.
I tried to rewrite the code, but it still doesn't work.
This is my code that works perfect:
if (obj != "finished") {
var cmd = "finished = ("+obj+"== target3)";
ggbApplet.debug(cmd);
ggbApplet.setErrorDialogsActive(false);
ggbApplet.evalCommand(cmd);
finished = ggbApplet.getValueString("finished");
if (finished.indexOf("true") > -1) {
ggbApplet.setVisible("step3",true);
}
}
If I replace the code for this one, it doesn't work anymore.
function checkpoint(target,step){
if (obj != "finished") {
var cmd = "finished = ("+obj+"== "+target+")";
ggbApplet.debug(cmd);
ggbApplet.setErrorDialogsActive(false);
ggbApplet.evalCommand(cmd);
finished = ggbApplet.getValueString("finished");
if (finished.indexOf("true") > -1) {
ggbApplet.setVisible(step,true);
}
}
}
checkpoint(target3,step3);
I really don't see what I'm doign wrong. obj is something that is defined somehwere else in the code. But I don't thing that is causing problems, as everything works perfect before I tried to write it as an function. Any further help is really appreciated.
The function is defined fine, apart from a possible spelling mistake in its name, but the use of the parameters is incorrect. You're passing in target and step as parameters but then not using those variables but using strings instead.
ggbApplet.setVisible("step",true);
should be
ggbApplet.setVisible(step, true);
and
var cmd = "finished = ("+obj+"== target)";
should be:
var cmd = "finished = ("+obj+"== " + target + ")";
This way you can pass in the strings of the target and the step and they should evaluate correctly.
There may be other issues with scoping and global variables, but its not possible to tell from this small snippet of code.
You have two different spellings:
function checpoint()
and
checkpoint(target, step1);
Also, is obj a global variable? I don't see where it's defined or passed to the function.
In addition, you should look in the browser error console to see what errors are reported there. That is the first place you should look when things aren't working as it will tell you about undefined variables, exceptions thrown, etc...

Get name from within a function defined with var

I need, from within a function, to get it's name (actually I'm going up the stack a bit with .caller but that shouldn't change the problem).
'arguments.callee.name' would solve my problem IF my function had been named. But my functions are declared with var myFunc = function() {}, and changing that is not a possibility (I'm using CoffeeScript which always compiles to var declarations).
So how could I get to the variable to which the function was assigned?
This is for debugging purposes so I'm not worried about performance, I'll use whatever operations get me to the name no matter the processing/time cost.
EDIT: For the record, this is what I implemented in CoffeeScript based on the chosen answer's recommended library:
window.log = (msg) ->
caller = printStackTrace()[4]
caller = caller.substring 0, caller.indexOf('(') - 1
if typeof msg is 'object'
console.log "v --- at #{ caller }: ---"
console.log msg
else console.log "> --- at #{ caller }: " + msg
Works like a charm, thanks everyone!
You might be interested in this javascript stacktrace project on github. In particular, note the findFunctionName method in stacktrace.js.
Basically they re-fetch the javascript source using XMLHTTPRequest and pull the line where the function was declared.
If you're using Google Chrome, you can use the Stack Tracing API to get at that information. See: http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi

Categories

Resources