Get function name in JavaScript - javascript

Does anyone know if there is a way to get JavaScript function name. For example I got a function like
function test1(){
alert(1);
}
I have it in my head section. Then I create an object obj1 and put my function there
obj1.func = test1;
When I call a method in obj1 object, do I have any way to get my function name (test1) inside of this method, except parsing the source (this.func.toString()) of the function.

function test() { alert(arguments.callee.name); }
b = test;
b();
outputs "test" (in Chrome, Firefox and probably Safari). However, arguments.callee.name is only available from inside the function.
If you want to get name from outside you may parse it out of:
b.toString();
but I think name property of function object might be what you need:
alert(b.name);
this however does not seem work for IE and Opera so you are left with parsing it out manually in those browsers.

Until ES2015, there was no standard way to get the name of a function. Most current browsers support a name property on Function objects that was non-standard until ES2015, but no current version of IE does. The only option this leaves you if you need to support IE is trying to parse the name from the function's string representation, which is not a good idea. There's a (long) discussion here about it: http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/b85dfb2f2006c9f0

The best thing to do is:
function functionName(fun) {
var ret = fun.toString();
ret = ret.substr('function '.length);
ret = ret.substr(0, ret.indexOf('('));
return ret;
}
Note: Using Function.caller is non-standard and arguments.callee is forbidden in strict mode.

Here's what I use to put class names in error messages. It includes code to get the name of functions, which works in most browsers.
Obviously, there is no standard way that always works, so you should always provide a name that can be used if no other name is found.
var nameFromToStringRegex = /^function\s?([^\s(]*)/;
/**
* Gets the classname of an object or function if it can. Otherwise returns the provided default.
*
* Getting the name of a function is not a standard feature, so while this will work in many
* cases, it should not be relied upon except for informational messages (e.g. logging and Error
* messages).
*
* #private
*/
function className(object, defaultName) {
var result = "";
if (typeof object === 'function') {
result = object.name || object.toString().match(nameFromToStringRegex)[1];
} else if (typeof object.constructor === 'function') {
result = className(object.constructor, defaultName);
}
return result || defaultName;
}

This is probably the best way to do it:
var myfunc = function () {};
var funcName = myfunc.constructor.name;
This can be done outside the execution of the function, and you can check within the context of the browser console.
Happy coding!

One interesting way I'm experimenting with is a declaration like the following:
var test1 = function test1(){
alert(1);
};
It's a little hacky, but what ends up happening is test1 is a local variable that holds a [Function: test1] object.
Here's what happens when you use code based on it:
test1(); //runs the function as expected
console.log(test1.name); //prints 'test1'
So if you do the following:
obj1.func = test1;
You'll then be able to reference obj1.func.name and it'll return 'test1'.

You could convert your function into a string (fn + '') and split it later at whitespace and open bracket /\s|\(/.
var getFunctionName = function (fn) {
return (fn + '').split(/\s|\(/)[1];
};

Related

A "safe place" to eval trusted code in Javascript (with specific context)? [Edit: how can you break it?]

Don't judge me yet on the title, I know eval is evil, but there are reasons I do it that way, and it will be very limited. Here is the thing: I want to create a safe space where i can run specific (and trusted) bits of code, and retrieve the result (if it fits to what i expect). For security reasons, I wanted to cut it from all other scopes (this space is asked for the result, and is supposed not to be able to export anything to surrounding scopes by itself).
I came to a solution which seems to work, that also can add a context to the execution, but i'm not sure if it is valid, or if there are security breaches in this system. Can you please tell me if there is something wrong with it?
It actually creates local vars with same name as the global ones, to prevent accessing to them. It also strips functions (I will add feature to preserve the ones I want to keep). The function is declared closest from globals as possible, to avoid visibility of local scopes that would be higher (a parameter to remove these specific local vars is planned).
function contextNoScope(root, context) {
//I had to pass window as parameter for it to work properly
for(var key in root){
if(key != '0' && key != 'window'){
eval('var ' + key + '=undefined;');
}
}
var window = undefined;
var root = undefined; //root has to be forbidden too
return function() {
this.eval = function(str){ return eval(str); };
return this;
}.call(context);
}
USAGE:
(function(root){
function contextNoScope(root, context) {
//...same as previous
}
var context = { x: 3 };
var space = contextNoScope(root, context);
console.log(space.eval('this.x + 1'));
})(window);
(NOTE: if you test this code in a global way, don't forget to add a special fix if you pass a global var for the context, because it will be masked like all the others. A fix has to be added also if you want try to pass window as the context parameter, for obvious reasons..)
EDIT:
To make things clearer about what the scripts do and what can solve my problem: I assume there is no total safety in JS with what can be called 'trusted source', as we are obviously talking here about importing scripts. By trusted I mean that the script origin will be checked, and security keys added, to begin with.
Each script takes a certain variable from the given context and adds a property to it. The names here are given, meaning that we know beforehand which var will be modified and what is the name and type of the property added to it. In a way I can already check if what is done was intended or not, the problem here is to be "sure" that any code won't be able to interfere with events or the DOM mostly, and doesn't remove or modify anything in the given context except adding the propery..
EDIT 2: please break it!
(I'm not yet specialist of all the site rules, correct me if it's not the way to properly edit: i chose not to modify the first code and add the new version, even if it gets a bit long.)
I am heading for a proper sandbox for my solution, made by better people than me, but because I am curious and want to keep learning, I post here an improved version of what i did, because I'd like to know how this still can be broken. So i am now looking for precise tricks that can break this system:
function contextNoScope(context) {
var len, i, keys, val, window = root, isNaN = root.isNaN, console = root.console;
if(!context){ context = {}; }
keys = Object.getOwnPropertyNames(window);
if(len = keys.length){
for(i = 0; i < len; i++){
val = keys[i];
//TODO: remove 'console' from the if (debug purpose)
if(isNaN(val) && val != 'window' && val != 'eval' && val != 'isNaN' && val != 'console'){
eval('var ' + val + '=undefined;');
}
}
}
isNaN = undefined;
len = undefined;
i = undefined;
keys = undefined;
val = undefined;
eval('var root = undefined');
return function() {
this.eval = function(str){
if(str){
str = str.toString();
//TODO: replace by more relevant regex (it currently throws error for words like 'evaluation')
if(str.indexOf('constructor') > -1 || str.indexOf('__proto__') > -1 || str.indexOf('prototype') > -1 || str.indexOf('eval') > -1){
console.log('ERROR - str contains forbidden code "constructor", "__proto__", "eval", "prototype"', '\n' + str);
return false;
}
try{
eval(str);
return true;
}catch(e){
console.log(e + '\nin:\n' + str);
return false;
}
}
console.log('ERROR - str is not defined: ', str);
return false;
};
return this;
}.call(context);
}
Some explanations for the changes:
In the first version i added window as a parameter because of a basic mistake about when the word var is evaluated, it is not necessary. But passing window as another name ('root' here) seems easier. The whole function is wrapped the same way as in the first version usage.
added getOwnPropertyNames to get also the non-enumerable properties, but I know about the backwards compatibility issue, that is not what I mean by 'break the system' to use an older browser (I know it already)
added masking of the function local parameters or variables
the test for isNaN(val) is here to not evaluate as a variable the numbers-properties of window, that reference the i-frames
eval('var root = undefined'); is a trick for the var to be created at the moment the line is executed, not at the very beginning, like it would be with a regular var
I am aware that functions declared in this space don't access regular functions anymore (try with an alert(1), it won't work)
Anything that's based on setting variables to shadow globals can be broken by Function.apply(undefined), which runs a function with this set to the global context. For instance:
(function() {
this.alert(1);
}).apply(undefined);
Anything that's based on regular expressions can probably be broken by some combination of:
Escaping
new Function, eval, etc
Constructing strings using non-alphanumeric Javascript expressions
Bottom line: You cannot build an effective sandbox out of Javascript. It's been tried; every attempt has been complicated, fragile, and eventually broken.

Accessing parameters when the function expects none Javascript

I am writing a Javascript function to count the number of instances of an element in an unsorted array. It has a method signature like this
Array.prototype.numberOfOccurrences = function() {
}
Here is an example of expected behavior
var arr = [4, 0, 4];
Test.assertEquals(arr.numberOfOccurrences(4), 2);
My problem is that I don't know how to access the elements in the array. The function doesn't take any parameters so how do I reference the array being passed in?
Note: The instructions aren't very descriptive for this kata on code wars and adding a parameter to the function returns some error unexpected token.
Inside the function you are creating into the Array.prototype you can access all the prototype functions through the "this" keyword.
Meaning you can access the array items using numeric properties like this[0] or this[1] to a access the first and second item respectively.
You can also call functions which allows you to iterate over each item on the array, such as: forEach, filter, etc.
Please refer this page to see everything you can do with the array prototype:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype
Lastly don't forget that the JavaScript implementation varies on each browser, so a function that works on Chrome, might not work on InternetExplorer, always confirm on caniuse.com If the function you are used has the same implementation on your targets browsers.
Cheers.
Whether you should extend javascript base objects aside, this is your friend:
Array.prototype.numberOfOccurrences = function(valueToFind) {
return this.filter(function(item) {
return item === valueToFind;
}).length;
}
var a = [1,2,3,3,3,3];
console.log(a.numberOfOccurrences(3)); //4
As noted above, if you're not able to change the function signature for whatever reason you can specify it as follows:
Array.prototype.numberOfOccurrences = function() {
var valueToFind = arguments[0];
...
}
I would recommend adding the parameter to the function for clarities sake. Seems counter intuitive for a function like numberOfOccurences to not take in a parameter - numberOfOccurences of what?
Fiddle: http://jsfiddle.net/KyleMuir/g82b3f98/
You might try using the locally available variable 'arguments' inside of the function. So for example, your code might look like thsi:
Array.prototype.numberOfOccurrences = function() {
var args = arguments || {};
var testArray, testCheck;
if (args[0] && Array.isArray(args[0]) {
// do something with the array that was the first argument, like:
testArray = args[0];
testCheck = testArray.indexOf(args[1]);
return testCheck;
} else {
// do what you want to do if the function doesn't receive any arguments or the first argument
// received isn't an array.
}
}
'arguments' is always available to you inside a declared function.

Javascript IIFE as an object's property (method)

I'm trying to use an IIFE as a method (which might be wrong).
Why ? Because, I'm trying to implement the proxy design pattern.
In adobe extendscript, there is an "app" object to access documents, etc, like -
var length = app.activeDocument.length; // or some other property
Now, I wanted to put a proxy around "app". So I created a proxy object -
var AppProxy = {
activeDocument: function() { // do stuff...; return app.ActiveDocument; }
}
But now, this is how I had to access it -
var length = AppProxy.activeDocument().length;
But this is how I want to access it -
var length = AppProxy.activeDocument.length; // no parenthesis
So I read about IIFE, and ended up doing this -
var AppProxy = {
activeDocument: (function() {
// do stuff...;
return app.ActiveDocument; })()
}
And as expected, the AppProxy.activeDocument gets called automatically when AppProxy is defined, i.e. even BEFORE it reaches var length = AppProxy.activeDocument.length.
So how do I prevent this from happening when AppProxy is defined as an object literal ?
Is there a workaround to my requirement ?
Thanks.
But this is how I want to access it -
var length = AppProxy.activeDocument.length; // no parenthesis
To do that, you need to define activeDocument as a property with a getter function. This is possible in browsers with proper support for ES5's getters and setters, which is all modern browsers (not IE8 and earlier). (Before ES5, there was a never-standardized syntax for this that some browsers supported, but again not IE8 or earlier).
In ES5, you can do this either with Object.defineProperty or by defining a getter in an object initializer. Here's Object.defineProperty:
// ES5+ only
var AppProxy = {};
Object.defineProperty(AppProxy, "activeDocument", {
get: function() {
// do stuff...;
return app.ActiveDocument;
}
});
Here's doing it as part of the object initializer:
// ES5+ only
var AppProxy = {
get activeDocument() {
// do stuff...;
return app.ActiveDocument;
}
};
Having done either of those, then this:
var length = AppProxy.activeDocument.length;
...runs that function, even though it doesn't look like it does. The function call still happens, it's just hidden.
But if you need to support obsolete browsers (even here in mid 2016, IE8 still has ~5% market share) or if you don't want to hide the fact you're calling a function, just call the function:
var length = AppProxy.activeDocument().length;

JS: Get the var name

I have this code here:
var myVar = 'this is a string';
I want to get the string representation of the variable name myVar. This is a very simplified example. Obviously we know it's myVar but it demonstrates my need.
I need to run a function like this:
function getVarName(v) {
return v.blah;
}
var nameOfVar = getVarName(myVar); //should 'myVar'
Is this possible? I'm not worried about cross-browser, it's for a firefox addon so I can use the latest >= ES5.
Thanks
Edit: I wanted to add the reason I was doing this, it was to dump some objects in firefox system, it helps me make addons. I know the key/value thing in objects, but in case the function gets run on a string or some non-object it would be nice to know the var name it got run on. It runs on bunches of stuff automatically so I don't know the var names.
That is not possible. It won't be sent as it is in the method call.
getVarName("var");
function getVarName(variableName) {
/* this would be var */
}
The function has its own parameter for that variable. However, you can get the value in that variable.
That isn't how variables work in JavaScript.
If you want to maintain a mapping of strings to values, use an object:
values = { myVar: 'this is a string' }
I know you have mentioned you don't want objects to be involved. But have a look at this one:
const getVarName = (variable) => {
let varName = '';
for (let key in variable) varName = key;
return varName;
}
const myVar = 'some string';
// Place your string inside curly braces
const nameOfVar = getVarName({myVar});
console.log(nameOfVar); // output: 'myVar'

Security considerations using "new Function(...)" (during rendertime, expression coming from my Javascript sources)

I'd like to use new Function(...) to generate a function from very reduced code. I'l like to do this to
avoid parsing the expression on my own and
being as flexible as possible.
I avoid eval() whenever possible. But I'm not sure if it's secure enough to use new Function(...) which is also known as being liable to security holes.
Background
I want to manage the states of menu buttons. So, while defining the buttons, I'd like to write something like
{
..., // More button definition
state: "isInEditmode && (isWidgetSelected || isCursorInWidget),
...
}
While handling the statechange during several events I'll check (summarize) the states of the current overall state object against those in the states attribute.
So I'll generate a Function during rendertime and attaching it as a DOM object attribute, not DOM attribute this way:
...
$el.stateFn = new Function("stateObj", "with (stateObj) {return " + item.state + ";}");
...
Testing state:
visible = $el.stateFn.call(currentStates, currentStates);
The with statement helps me providing the current state object's attributes as variables so that the above expression does not need something like obj.isInEditmode.
Security question
In my opinion this does not introduce security holes as the function attached to the DOM object is generated during render time and read from source. Or am I wrong? Should I avoid this?
Performance hints are appreciated (comment) (I think as long as I evaluating a new Function once during render time, this is acceptable).
Edit 1
I'm using Backbone.js. Using another Framework is out of question.
Some menu items need to be bound to different or even multiple models.
Delegation (or facade / proxy?) models are considerable.
Security-wise both are just as bad if user input is allowed to break out in the code. However, maintenance wise you don't have to worry about hidden bugs when local eval messes with your scope and causes dynamic scoping.
Performance-wise the function generated by new Function is exactly the same as any other function. The generation is slower but inlike eval it doesn't cause the containing scope to be unoptimizable.
In fact, new Function can be used to improve performance in situations like:
//Will behave like function a( obj ) { return obj.something }
function makePropReader( propName ) {
return new Function( "obj", "return obj." + propName );
}
The constructed function will perform better than the function returned here:
function makePropReader( propName ) {
return function( obj ) {
return obj[propName];
}
}
Due to having to dynamically read propName from closure context and do a dynamic read on the object everytime it is called.
Please never ever use eval no matter what. There is a much better alternative. Instead of eval, use the Function constructor. eval is evil, and there's no question about that, but most people skip over the most evil aspect of eval: it gives you access to variables in your local scope. Back in the 90s, back before the concept of JIST compilation, eval sounded like a good idea (and it was): just insert some additional lines dynamically into the code you're already executing line-by-line. This also meant that evals didn't really slow things down all. However, now-a-days with JIST compilation eval statements are very taxing on JIST compilers which internally remove the concept of variable names entirely. For JIST compilers, in order to evaluate an eval statement, it has to figure out where all of its variables are stored, and match them with unknown globals found in the evaled statement. The problem extends even deeper if you get really technical.
But, with Function, the JIST compiler doesn't have to do any expensive variable name lookups: the entire code block is self-contained and in the global scope. For example, take the following terribly inefficient eval snippet. Please note that this is only for the purpose of being an example. In production code, you shouldn't even be using eval or Function to generate a function from a string whose content is already known.
var a = {
prop: -1
};
var k = eval('(function(b){return a.prop + b;})');
alert( k(3) ); // will alert 2
Now, let's take a look at the much better Function alternative.
var a = {
prop: -1
};
var k = (Function('a', 'b', 'return a.prop + b')).bind(undefined, a);
alert( k(3) ); // will alert 2
Notice the difference? There is a major one: the eval is executed inside the local scope while the Function is executed inside the global one.
Now, onto the next problem: security. There is a lot of talk about how security is difficult, and yes, with eval it is pretty much impossible (e.x. if you wrap the whole code in a sandboxing function, then all you have to do is prematurely end the function and start a new one to execute code freely in the current scope). But, with Function, you can easily (but not the most efficiently) sandbox anything. Look at the following code.
var whitelist = ['Math', 'Number', 'Object', 'Boolean', 'Array'];
var blacklist = Object.getOwnPropertyNames(window).filter(function(x){
return whitelist.indexOf(x) === -1 && !/^[^a-zA-Z]|\W/.test(x)
});
var listlen = blacklist.length;
var blanklist = (new Array(listlen+1)).fill(undefined);
function sandboxed_function(){
"use-strict";
blacklist.push.apply(blacklist, arguments);
blacklist[blacklist.length-1] =
'"use-strict";' + arguments[arguments.length-1];
var newFunc = Function.apply(
Function,
blacklist
);
blacklist.length = listlen;
return newFunc.bind.apply(newFunc, blanklist);
}
Then, fiddle around with the whitelist, get it just the way you want it, and then you can use sandboxed_function just like Function. For example:
var whitelist = ['Math', 'Number', 'Object', 'Boolean', 'Array'];
var blacklist = Object.getOwnPropertyNames(window).filter(function(x){
return whitelist.indexOf(x) === -1 && !/^[^a-zA-Z]|\W/.test(x)
});
var listlen = blacklist.length;
var blanklist = (new Array(listlen+1)).fill(undefined);
function sandboxed_function(){
"use-strict";
blacklist.push.apply(blacklist, arguments);
blacklist[blacklist.length-1] =
'"use-strict";' + arguments[arguments.length-1];
var newFunc = Function.apply(
Function,
blacklist
);
blacklist.length = listlen;
return newFunc.bind.apply(newFunc, blanklist);
}
var myfunc = sandboxed_function('return "window = " + window + "\\ndocument = " + document + "\\nBoolean = " + Boolean');
output.textContent = myfunc();
<pre id="output"></pre>
As for writing code to be runned under this strict sandbox, you may be asking, if window is undefined, how do I test for the existence of methods. There are two solutions to this. #1 is just simply to use typeof like so.
output.textContent = 'typeof foobar = ' + typeof foobar;
<div id="output"></div>
As you can see in the above code, using typeof will not throw an error, rather it will only just return undefined. The 2nd primary method to check for a global is to use the try/catch method.
try {
if (foobar)
output.textContent = 'foobar.constructor = ' + foobar.constructor;
else
output.textContent = 'foobar.constructor = undefined';
} catch(e) {
output.textContent = 'foobar = undefined';
}
<div id="output"></div>
So, in conclusion, I hope my code snippets gave you some insight into a much better, nicer, cleaner alternative to eval. And I hope I have aspired you to a greater purpose: snubbing on eval. As for the browser compatibility, while the sandboxed_function will run in IE9, in order for it to actually sandbox anything, IE10+ is required. This is because the "use-strict" statement is very essential to eliminating much of the sneaky sand-box breaking ways like the one below.
var whitelist = ['Math', 'Number', 'Object', 'Boolean', 'Array'];
var blacklist = Object.getOwnPropertyNames(window).filter(function(x){
return whitelist.indexOf(x) === -1 && !/^[^a-zA-Z]|\W/.test(x)
});
var listlen = blacklist.length;
var blanklist = (new Array(listlen+1)).fill(undefined);
function sandboxed_function(){
blacklist.push.apply(blacklist, arguments);
blacklist[blacklist.length-1] =
/*'"use-strict";' +*/ arguments[arguments.length-1];
var newFunc = Function.apply(
Function,
blacklist
);
blacklist.length = listlen;
return newFunc.bind.apply(newFunc, blanklist);
}
var myfunc = sandboxed_function(`return (function(){
var snatched_window = this; // won't work in strict mode where the this
// variable doesn't need to be an object
return snatched_window;
}).call(undefined)`);
output.textContent = "Successful broke out: " + (myfunc() === window);
<pre id="output"></pre>
One last final comment is that if you are going to allow event API's into your sandboxed environment, then you must be careful: the view property can be a window object, making it so you have to erase that too. There are several other things, but I would recommend researching thoroughly and exploring the objects in Chrome's console.
Lastly, note that Function is a very unique constructor which returns a function instead of an object instance, so there's no need to use new.
Old thread with answers considered dangerous these days.
new Function() still allows access to global variables. So an adversary, when given the chance to effect the function string - which is usually the very reason for considering new Function and hard to guarantee it can't be done maliciously -, can read and modify any global. Good luck from that point on :-)
Which is why new Function falls under the same category as eval from the viewpoint of CSP (Content Security Policy) as mentioned here.
Example:
a = 10
> 10
b = new Function('a = 20; return 42')
> function(...)
a
> 10
b()
> 42
a
> 20
As you have said that you will only be doing this on code you wrote yourself - I'd say that it's fine. new Function() is definitely better than using eval() in any case. You won't be messing with any local variables and you're enforcing your own context by using fn.call.
It seems to me that the problem you are trying to solve would be fairly straight forward if you were using an MVC or MVVM framework that supports 2 way data binding. I.e. changing the UI updates a backing model and updating the model will automatically refresh the UI for you.
For example, knockout.js. In this case the visible databinding would be appropriate.

Categories

Resources