2

Consider these script fragments.

<script data-name="script1">
    foo();
</script>

<script data-name="script2">
    foo();
</script>

<script>
    function foo(){
//      console.log(arguments.?);
    }
</script>

Is there a way to find out which script function foo was called from the line denoted by the "//"?

Kara
  • 6,115
  • 16
  • 50
  • 57
user1277170
  • 3,127
  • 3
  • 19
  • 19
  • 1
    The answer will be "no". – epascarello Nov 20 '13 at 19:05
  • 4
    No, as functions don't carry information about the script tag they were defined within. What is your use-case with this? Perhaps you just need a different approach to accomplish your goal – Rob M. Nov 20 '13 at 19:05
  • @RobM. I have a 1:1 relation between a script and an object, and was hoping to be able to have a global, transparent function to map. (Rather than each script having to map itself.) – user1277170 Nov 20 '13 at 19:14
  • I *think* I understand what you are trying to accomplish. Is each script tag actually calling a function or defining an object? If it's an object you elaborate with a more concrete example? – Rob M. Nov 20 '13 at 19:19
  • @RobM. Let's say the main script is a database wrapper, and for each script it makes a table. foo is a function to run an operation on the correct table. Ideally I'd like it so a third party making a script wouldn't have to explicitly identify with each function call. – user1277170 Nov 20 '13 at 19:24
  • [relevant](http://stackoverflow.com/q/403967/497418) – zzzzBov Nov 20 '13 at 19:44
  • https://developer.mozilla.org/en-US/docs/Web/API/document.currentScript – Dagg Nabbit Nov 20 '13 at 20:03

2 Answers2

2

As already mentioned in the comments, the way you present it, this is not possible, it only works if the function foo is called from a function, which then of course has to be a different function for each script, then you can use

console.log(arguments.callee.caller.name)

That will give you the name of the function that called your function foo.

Edit: and really, if it's important to know from where the script was called, just use an argument, like function foo(caller){, which indicates how the function was called, that's much safer than relying on the arguments.callee.caller thing.

rolfv1
  • 571
  • 3
  • 14
  • I was thinking of wrapping, but it just returns the anonymous function. (I.e. name="") As for the edit, having to identify for every function call out is precisely why I wanted to make it transparent. – user1277170 Nov 20 '13 at 19:20
  • 4
    **Warning**: The 5th edition of ECMAScript (ES5) forbids use of `arguments.callee()` in [strict mode](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode). [See why](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments/callee?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FFunctions_and_function_scope%2Farguments%2Fcallee#Why_was_arguments.callee_removed_from_ES5_strict_mode.3F) – Oriol Nov 20 '13 at 19:20
  • I completely agree Oriol, that's why I would only use the `arguments.callee` for debugging of your scripts during development (which I assumed in this case, as it was only used for a console log). As for the anonymous functions, yeah that won't work, and the only way to do the identification then is by looking at some unique property of the objects that you are working with, or still, by using an argument in the function call. – rolfv1 Nov 20 '13 at 19:26
  • The problem with passing the caller as an argument, though, is that it is unreliable. One conceivable use case of determining the caller could be some sort of access control (i. e. to forbid scripts from particular sites access to the function(s) in question), and in order to bypass that, the script in question could attempt to forge the caller argument. – Robidu Mar 15 '21 at 16:24
0

Ok, I figured it out, this will grab the script data-name attribute

function foo() {
    var parentScript = document.body.lastChild;
    console.log(parentScript.getAttribute('data-name'));
}

To get it to work I had to define the foo function above the calls to it, but I'm sure some playing around with it could resolve that.

Rob M.
  • 35,491
  • 6
  • 51
  • 50
  • 1
    Not sure why this was downvoted...jQuery dependency? Would love some elaboration on that – Rob M. Nov 20 '13 at 19:55
  • Wasn't me, but whilst that's probably technically right per se, it only works as the DOM is loaded. Once loaded, it will always return the last script. – user1277170 Nov 20 '13 at 19:57
  • Fair enough, well this was my best guess; the link that @zzzzBov posted is probably a better solution – Rob M. Nov 20 '13 at 19:59
  • I downvoted it for 1) unnecessary, unspecified dependency which Q was not tagged for, 2) it may not work if scripts are being inserted into the body (using something like JSONP; the same problem exists in the question zzzzBov linked). See also http://stackoverflow.com/questions/14410748/ – Dagg Nabbit Nov 20 '13 at 20:02
  • Again, that's fair; but just to be clear: OP didn't state that scripts were going to be inserted after DOM loaded and given the top-down processing of their example, a simple removal of the jQ dependency would accomplish the goal as stated. – Rob M. Nov 20 '13 at 20:09
  • A simple remove of the dependency would also remove my downvote ;) (I do prefer the `document.write` approach, though. Both only work on load, but using `document.write` you can at least not worry about other scripts being inserted. http://jsfiddle.net/Sg6Vg/ ) – Dagg Nabbit Nov 20 '13 at 20:10