Related
I've done a lot of searching and some playing around, and I'm pretty sure the answer to this question is no, but I'm hoping a JavaScript expert might have a trick up his sleeve that can do this.
A JavaScript function can be referenced by multiple properties, even on completely different objects, so there's no such thing as the object or property that holds the function. But any time you actually call a function, you must have done so via a single object (at the very least, the window object for global function calls) and property on that object.
(A function can also be called via a function-local variable, but we can consider the function-local variable to be a property of the activation object of the scope, so that case is not an exception to this rule.)
My question is, is there a way to get that property name that was used to call the function, from inside the function body? I don't want to pass in the property name as an argument, or closure around a variable in an enclosing scope, or store the name as a separate property on the object that holds the function reference and have the function access that name property on the this object.
Here's an example of what I want to do:
var callName1 = function() { var callName = /* some magic */; alert(callName); };
var obj1 = {'callName2':callName1, 'callName3':callName1 };
var obj2 = {'callName4':callName1, 'callName5':callName1 };
callName1(); // should alert 'callName1'
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'
From my searching, it looks like the closest you can get to the above is arguments.callee.name, but that won't work, because that only returns the name that was fixed to the function object when it was defined, and only if it was defined as a named function (which the function in my example is not).
I also considered that maybe you could iterate over all properties of the this object and test for equality with arguments.callee to find the property whose value is a reference to the function itself, but that won't work either (in the general case), because there could be multiple references to the function in the object's own (or inherited) property set, as in my example. (Also, that seems like it would be kind of an inefficient solution.)
Can this be done?
Short answer:
No, you cannot get "the property name" used to call your function.
There may be no name at all, or multiple names across different scopes, so "the property name" is pretty ill defined.
arguments.callee is deprecated and should not be used.
There exists no solution that does not use arguments or closure.
Long answer:
As thefourtheye commented, you should rethink what you are trying to do and ask that instead in a new question. But there are some common misconceptions, so I will try to explain why you cannot get the "simple property name".
The reason is because it is not simple.
Before we go ahead, let us clarify something. Activation Objects are not objects at all.
The ECMAScript 5.1 specification calls them Environment Records (10.2.1), but a more common term is Scope chain.
In a browser the global scope is (often) the window object, but all other scopes are not objects.
There may be an object that you use to call a function, and when you call a function you must be in some scope.
With few exceptions, scopes are not objects, and objects are not scopes.
Then, there are many names.
When you call a function, you need to reference it, such as through an object property. This reference may have a name.
Scope chain has declarations, which always have a name.
A Function (the real function, not reference) may also have a function name - your arguments.callee.name - which is fixed at declaration.
Not only are they different names, they are not (always) the "the property name" you are seeking.
var obj = { prop : function f(){} }, func = obj.prop;
// "obj" and "func" are declarations.
// Function name is "f" - use this name instead of arguments.callee
// Property name is "prop"
func(); // Reference name is "func"
obj.prop(); // Reference names are "obj" and "prop"
// But they are the same function!
// P.S. "this" in f is undefined (strict mode) or window (non-strict)
So, a function reference may comes from a binding (e.g. function declaration), an Object (arguments.callee), or a variable.
They are all References (8.7). And reference does have a name (so to speak).
The catch is, a function reference does not always come from an object or the scope chain, and its name is not always defined.
For example a common closure technique:
(function(i){ /* what is my name? */ })(i)
Even if the reference does have a name, a function call (11.2.3) does not pass the reference or its name to the function in any way.
Which keeps the JavaScript engine sane. Consider this example:
eval("(new Function('return function a(){}'))()")() // Calls function 'a'.
The final function call refers the eval function, which refers the result of a new global scope (in strict mode, anyway), which refers a function call statement, which refers a group, which refers an anonymous Function object, and which contains code that expresses and returns a function called 'a'.
If you want to get the "property name" from within a, which one should it get? "eval"? "Function"? "anonymous"? "a"? All of them?
Before you answer, consider complications such as function access across iframes, which has different globals as well as cross origin restriction, or interaction with native functions (Function.prototype.bind for example), and you will see how it quickly becomes hell.
This is also why arguments.caller, __caller__, and other similar techniques are now all deprecated.
The "property name" of a function is even more ill defined than the caller, almost unrealistic.
At least caller is always an execution context (not necessary a function).
So, not knowing what your real problem is, the best bet of getting the "property name" is using closure.
there is no reflection, but you can use function behavior to make adding your own fairly painless, and without resorting to try/catch, arguments.callee, Function.caller, or other strongly frowned-upon behavior, just wasteful looping:
// returning a function from inside a function always creates a new, unique function we can self-identify later:
function callName() {
return function callMe(){
for(var it in this) if(this[it]===callMe) return alert(it);
}
};
//the one ugly about this is the extra "()" at the end:
var obj1 = {'callName2':callName(), 'callName3':callName() };
var obj2 = {'callName4':callName(), 'callName5':callName() };
//test out the tattle-tale function:
obj1.callName2(); // alerts 'callName2'
obj2.callName5(); // alerts 'callName5'
if you REALLY want to make it look like an assignment and avoid the execution parens each time in the object literal, you can do this hacky routine to create an invoking alias:
function callName() {
return function callMe(){
for(var it in this) if(this[it]===callMe) return alert(it);
}
};
//make an alias to execute a function each time it's used :
Object.defineProperty(window, 'callNamer', {get: function(){ return callName() }});
//use the alias to assign a tattle-tale function (look ma, no parens!):
var obj1 = {'callName2': callNamer, 'callName3': callNamer };
var obj2 = {'callName4': callNamer, 'callName5': callNamer };
//try it out:
obj1.callName2(); // alerts 'callName2'
obj2.callName5(); // alerts 'callName5'
all that aside, you can probably accomplish what you need to do without all the looping required by this approach.
Advantages:
works on globals or object properties
requires no repetitive key/name passing
uses no proprietary or deprecated features
does not use arguments or closure
surrounding code executes faster (optimized) than
a try/catch version
is not confused by repeated uses
can handle new and deleted (renamed) properties
Caveats:
doesn't work on private vars, which have no property name
partially loops owner object each access
slower computation than a memorized property or code-time repetition
won't survive call/bind/apply
wont survive a setTimeout without bind() or a wrapper function
cannot easily be cloned
honestly, i think all the ways of accomplishing this task are "less than ideal", to be polite, and i would recommend you just bite the coding bullet and pass extra key names, or automate that by using a method to add properties to a blank object instead of coding it all in an object literal.
Yes.
Sort Of.
It depends on the browser. (Chrome=OK, Firefox=Nope)
You can use a factory to create the function, and a call stack parsing hack that will probably get me arrested.
This solution works in my version of Chrome on Windows 7, but the approach could be adapted to other browsers (if they support stack and show the property name in the call stack like Chrome does). I would not recommend doing this in production code as it is a pretty brittle hack; instead improve the architecture of your program so that you do not need to rely on knowing the name of the calling property. You didn't post details about your problem domain so this is just a fun little thought experiment; to wit:
JSFiddle demo: http://jsfiddle.net/tv9m36fr/
Runnable snippet: (scroll down and click Run code snippet)
function getCallerName(ex) {
// parse the call stack to find name of caller; assumes called from object property
// todo: replace with regex (left as exercise for the reader)
// this works in chrome on win7. other browsers may format differently(?) but not tested.
// easy enough to extend this concept to be browser-specific if rules are known.
// this is only for educational purposes; I would not do this in production code.
var stack = ex.stack.toString();
var idx = stack.indexOf('\n');
var lines = ex.stack.substring(idx + 1);
var objectSentinel = 'Object.';
idx = lines.indexOf(objectSentinel);
var line = lines.substring(idx + objectSentinel.length);
idx = line.indexOf(' ');
var callerName = line.substring(0, idx);
return callerName;
}
var Factory = {
getFunction: function () {
return function () {
var callName = "";
try {
throw up; // you don't *have* to throw to get stack trace, but it's more fun!
} catch (ex) {
callName = getCallerName(ex);
}
alert(callName);
};
}
}
var obj1 = {
'callName2': Factory.getFunction(),
'callName3': Factory.getFunction()
};
var obj2 = {
'callName4': Factory.getFunction(),
'callName5': Factory.getFunction()
};
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'
I'm writing an API and I need to execute a ternary inside a "getter" function for various fields. This works fine but I don't want the end user to have to use parentheses when accessing these fields.
Strangely the getter code actually executes when I access the field without the parentheses but I'm wondering if this is normal for javascript or if this is browser dependent? Currently using Firefox 31.
This works:
var theScript = Scripts.jQuery_1_11_1_js(); // Note I'm using the parentheses
This also works even without parentheses. How?:
var theScript = Scripts.jQuery_1_11_1_js; // Note the lack of parentheses
Example API:
var Scripts = (function () {
function Scripts() {
}
Scripts.isProduction = false;
Scripts.Url = "/Scripts";
Scripts.jQuery_1_11_1_js = function () {
return Scripts.isProduction ? Scripts.Url + "/jQuery_1_11_1.min.js" : Scripts.Url + "/jQuery_1_11_1.js";
}
return Scripts;
})();
var theScript = Scripts.jQuery_1_11_1_js();
var theScript = Scripts.jQuery_1_11_1_js; /// why does this work?
This also works even without parentheses. How?:
var theScript = Scripts.jQuery_1_11_1_js; // Note the lack of parentheses
No, it doesn't. The line executes just fine, but it doesn't call Scripts.jQuery_1_11_1_js, it just sets the value of theScript to a reference to the function Scripts.jQuery_1_11_1_js.
There are only two four (as of ES2015) ways I know of to call a function without parentheses:
Define the property on Scripts as an ES5 getter. Here's the ES5 syntax for doing that:
Object.defineProperty(Scripts, "jQuery_1_11_1_js", {
get: function() {
return Scripts.isProduction ? Scripts.Url + "/jQuery_1_11_1.min.js" : Scripts.Url + "/jQuery_1_11_1.js";
}
});
Now, the line
var theScript = Scripts.jQuery_1_11_1_js;
...will call that anonymous function we defined as the getter for the property.
Unfortunately, you can't do that in IE8. In IE8 (bizarrely), Object.defineProperty can only create properties on DOM elements, not normal objects. IE9 supports it properly.
Just for completeness, there is a second way, with new:
var foo = new Foo;
...which is equivalent to
var foo = new Foo();
But of course, you don't want to do that unless Foo is meant to be a constructor function, as it creates an object to pass to Foo as this.
Calling a tag function:
someFunction`template contents here`;
That doesn't look like a function call, but it is. It parses the template, evalutes any token expressions, and passes the raw form of the template (an array of strings with an added raw property, subsequent arguments for the token substitutions) into someFunction. Whereas someFunction(`template contents here`) would evaluate the template, evaluate any token expressions, and substitute them into the template producing a string, and then pass the string into someFunction. More on MDN.
Do just about anything on a Proxy object, since all the fundamental object operations (getting properties, setting properties, defining properties, getting its prototype, etc., etc.) can be trapped on proxies, generating a call to a trap handler.
Considering this code :
var o = {};
o.f = function(){};
new o.f;
Chrome prints o.f {} into the console. Do you know how this o.f part is called? More importantly, is there any way to get this result without using the console? I'd like to extract the name of a method from the function itself, that is to say, without any additional information.
I already know how to get the name in this case :
function f(){}
f+'' // "function f(){}"
But it does not behave the same way in the situation described above.
The following content is mostly copied from comments.
I wanted to know if there is a "technical" word to talk about this o.f pattern, let's say for example "namespace", "identifier", or "function path". Then, I was wondering if there was a way to retrieve this information from a loaded script in a webpage. The following question may help you in understanding my goal, the paragraph which is right after the first code block is quite close to my idea : Does Chrome retain each object's constructor?.
Maybe I should have mentioned that my original goal was to generate a documentation at runtime :/ Something like a reflection API would have been helpful in this case. More precisely, I was looking for a way to include the name of a method into the decompilated form of the function. Look :
function Class(){}
Class.prototype.method = function(){};
Class.prototype.method + '' gives function(){}. I'd like to inject the method's name to get this result : function method(){}.
The problem is that I don't have any information about which function I'm currently serializing since the operation occurs when the user clicks a link. I know I could easily store the name somewhere, binding the data to the anchor element for example, that's obvious to me, I was just curious to know if there was a way to retrieve this data the same way as Chrome.
Well, this seems a simple enough question, as far as the naming of all these constructs goes:
o.f = function(){};
is a common statement, consisting of even more common expressions. o.f is simply one of 2 ways to access an objects' properties, commonly referred to as the dot-notation. Though I believe in JS the dot (.) isn't really seen as an operator, I'll be referring to it as the member-of operator henceforth.
Next we have the well-known assignment-operator, which assigns the right-hand operand to the left (member of the object o, called f).
The right-hand expression (needs to be evaluated to a singular value) is a function definition that, instead of a statement on its own, is used as an expression. Given that fact, we refer to this usage of functions as function expressions.
In this particular case, the function has no name, it's an anonymous function. Internally, most -if not all engines- will give it a name, but that's not something JS should know or indeed care about. As far as JS is concerned, this function has no name, and is only accessible through o.f. If you call this function like so: o.f(), its context will be that of the object o, effectively making this function behave as a method.
So basically your statement reads like this: "Assign, and create if required, to the member of o called f, an anonymous function." The function itself has no name.
Consider this:
var o = {f: function(){console.log('I am a function');}};
var foobar = o.f;
foobar();//logs I am a function
So saying the name of the function o.f is f doesn't always apply. Other variables or properties can reference the same function. That's because functions are first class objects, they can be returned, passed to and assigned to, from and by anything.
The answer, then, is to use either one of these 2 approaches:
You can change the function expression by adding a name, to turn it into a named function expression:
f.o = function newName(){};
The newName name is, apart from older versions of IE, not available outside of the functions' scope. This is required by the ECMA specifications see the details here. Anyway, now we can check for that:
var func = function func(){console.log(func);};
//same name:
func();//logs function func(){}
var foobar = func;
foobar();//logs function func(){}
func = 123;//<-- no longer function
foobar();//still function func(){}//func is still accessible
var hidden = (function()
{
return function named()
{
console.log(named);//access name
};
}());
hidden();//logs function named(){}
console.log(named);//undefined -> not visible outside the function itself
The name of the function is restricted to its own scope.
Use a regex, which is slightly hacky, and doesn't pick up on two variables/properties referencing the same function object:
o = {f: function(){console.log('I am a function');}};
for (var pName in o)
{//probably add o.hasOwnProperty(pName) check to be safe
if (o[pName] instanceof Function)
{
console.log(o.f.toString().replace(
/^function\s*\(/,
'function o.'+pName+'(')
);
}
}
This stringifies the function (giving function (){/*body*/}) and replaces function ( with function <propertyName>(. If the function already had a name of its own, that name is not replaced.
In general, this is not common practice in Javascript or in programming in general.
However, functions do have an attribute name - see Function.name.
but in your code o.f is a nameless function.
var o = {};
o.f = function(){}; //function (){} creates a nameless function.
you can define a name before the ()
var o = {};
o.f = function f(){}; //function f(){} creates a function with the name f
then
o.f.name == 'f'
NOTE: this functionality is NOT supported in IE, and is not a specification of EMCA
This is exposed as the name property of the function, and these day it is part of the standard (search for SetFunctionName in the spec). See also MDN, Chrome Platform Status, browser support. If you are asking specifically about the feature of auto-guessing the name from the variable name for anonymous functions, MDN calls that the inferred function name.
Back when the question was asked, the definitive discussion of this topic was kangax's article Named function expressions demystified (now a bit outdated).
I haven't found any complete cross-browser doc of this variable.
What is arguments.callee for? how does it work?
Which arguments does it have?
arguments.callee is a reference to the function that is currently being called. First things first: don't use it: if you're in a strict context, it'll just spew errors.
However, personally -and I'm not alone in this- I'll miss this property. Before I get to explain why, I'll give you a pseudo-example of when you might use this:
var looper = (function(someClosureVar)
{
setTimeout((function(resetTimeout)
{
return function()
{
//do stuff, stop OR:
resetTimeout();
};
}(arguments.callee)),1000);
}(document.getElementById('foobar')));
I hope you like closures, because I do - and that's where arguments.callee are very likely to occur. The next-to-last line is where the money is:
(arguments.callee)
Is a reference to the anonymous function that sets the initial timeout, within a closure scope (that has access to 1 DOM element, in this case). Anonymous functions are GC'ed after they return, but in this case, I've added it to the timeout callback's scope (passed it as an argument to another anonymous function that returns the actual callback), so it is still referenced somewhere. Now, if you're in strict you needn't worry because this is what the code would look like in strict mode:
var looper = (function tempName(someClosureVar)
{
setTimeout((function(resetTimeout)
{
return function()
{
//do stuff, stop OR:
resetTimeout();
};
}(tempName)),1000);
}(document.getElementById('foobar')));
Name the function and that's it. Why don't I like it? arguments.callee raises flags, just like anonymous functions that some closure trickery is going on. I guess it's just a habit, but its one that, I feel, helps me to structure and debug my code more easily.
Couple that with a pathological hatred for IE, which comes natural to anyone doing some client-side scripting. IE versions that don't support strict mode, tend to leak the function name to the global namespace, thus never allowing the memory associated with the function (and the closure we've created) to be GC'ed. Which might lead to circular references, and, worse still, circular DOM references, which can lead to memory-leaks.
Actually: here's another, real example of where arguments.callee is used: event delegation and detaching event listenershere's some more info on JS strict mode and recursion using arguments.callee.
The last question has, IMO the most clear cut example of how arguments.callee is handy: recursive replacing functions:
function someF(foo)
{
//'use strict'; <-- would throw errors here
foo = foo.replace(/(a|b)+/gi, function (p1,p2)
{
if (p1.match(/(a|b){2,}/i))
{
return p1.replace(/(a|b)/gi,arguments.callee);//recursive
}
return (p2.match(/a/i) ? 'X':'Y');
});
}
As requested arguments.callee on MDN, warns for usage in strict mode (ECMA 5, that explains why DC says arguments.callee is deprecated)And more on strict
It specifies the currently executing function, so arguments.callee is the current function. It may be helpfull if you need to go recursive in anonimous function. Here example from mozilla:
function create() {
return function(n) {
if (n <= 1)
return 1;
return n * arguments.callee(n - 1);
};
}
var result = create()(5); // returns 120 (5 * 4 * 3 * 2 * 1)
Calee is part of the ECMAScript 3 standard, so it should be safe for cross-browser use. Callee holds the function that is currently executing and invoking it will invoke the current function. Therefore callee takes exactly the same arguments as the enclosing function (or rather it is the current function). Some more information is available here: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee
It is considered bad style to use callee. Give you function a name instead and use this name...
arguments.callee is a round about way of knowing the current executing function by asking 'Who is calling this specific argument?' . . . .
function factorial(a){
if(a>0)
return a*arguments.callee(a-1);
}
Here if you call factorial(5), it will check for condition greater than 0, and if it is true, will execute the same logic for the next lesser number . . . In some cases you don't know the name of the function to be called . . . .so you can use this property
here is a good reference
arguments.callee from MDN
UPDATE: arguments.callee() is deprecated in ES5
callee is a property of the arguments object. It can be used to refer to the currently executing function inside the function body of that function.
MDN docs here
(function()
{
//codehere
}
)();
What is special about this kind of syntax?
What does ()(); imply?
The creates an anonymous function, closure and all, and the final () tells it to execute itself.
It is basically the same as:
function name (){...}
name();
So basically there is nothing special about this code, it just a 'shortcut' to creating a method and invoking it without having to name it.
This also implies that the function is a one off, or an internal function on an object, and is most useful when you need to the features of a closure.
It's an anonymous function being called.
The purpose of that is to create a new scope from which local variables don't bleed out. For example:
var test = 1;
(function() {
var test = 2;
})();
test == 1 // true
One important note about this syntax is that you should get into the habit of terminating statements with a semi-colon, if you don't already. This is because Javascript allows line feeds between a function name and its parentheses when you call it.
The snippet below will cause an error:
var aVariable = 1
var myVariable = aVariable
(function() {/*...*/})()
Here's what it's actually doing:
var aVariable = 1;
var myVariable = aVariable(function() {/*...*/})
myVariable();
Another way of creating a new block scope is to use the following syntax:
new function() {/*...*/}
The difference is that the former technique does not affect where the keyword "this" points to, whereas the second does.
Javascript 1.8 also has a let statement that accomplishes the same thing, but needless to say, it's not supported by most browsers.
That is a self executing anonymous function. The () at the end is actually calling the function.
A good book (I have read) that explains some usages of these types of syntax in Javascript is Object Oriented Javascript.
This usage is basically equivalent of a inner block in C. It prevents the variables defined inside the block to be visible outside. So it is a handy way of constructing a one off classes with private objects. Just don't forget return this; if you use it to build an object.
var Myobject=(function(){
var privatevalue=0;
function privatefunction()
{
}
this.publicvalue=1;
this.publicfunction=function()
{
privatevalue=1; //no worries about the execution context
}
return this;})(); //I tend to forget returning the instance
//if I don't write like this
See also Douglas Crockford's excellent "JavaScript: The Good Parts," available from O'Reilly, here:
http://oreilly.com/catalog/9780596517748/
... and on video at the YUIblog, here:
http://yuiblog.com/blog/2007/06/08/video-crockford-goodstuff/
The stuff in the first set of brackets evaluates to a function. The second set of brackets then execute this function. So if you have something that want to run automagically onload, this how you'd cause it to load and execute.
John Resig explains self-executing anonymous functions here.