JS: Get the var name - javascript

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'

Related

Destructuring same name object/key

I have an object that looks like this:
const test = {
test: []
}
if (test) { // if the object it's not empty I want to do something
// I tried this but it won't work:
let { test } = test
}
Any way of destructure the key from the object. It's a pain to always do test.test every time I want to access it's value. I can't change the names of any of it, so that is out of the question.
You'll need to check object if it is not empty like:
if (Object.keys(test).length){
And to deconstructure, you'll need to have different name as it cannot have same name:
let { test: testArr } = test
console.log(testArr)
As per the comment, commented by El Aoutar Hamza under the post of Dave Newton
But the assignment let { test } = test is done within a if statement, which means that test declared inside if should normally shadow the variable declared outside if, shouldn't it? why is it any different when using destructring?
I would like to state that it is not allowed to have same name coz, it will throw error. You cannot access the variable before its initialization.
When you define:
let { test } = test
It will behave like: (pseudo code to understand)
let test = undefined
{ test } = test
// this cannot be accessed as it's value is not initialized.
Hope, you're clear what I meant.

JavaScript: Finding a variable's value by its name, is eval acceptable here?

WARNING: As other have stated here, this problem is based upon an inflexible customer requirement. While the question is valid, you should definitely use the simpler solutions (ex: putting your settings in a single object) if possible!
I have an array of variables I want to be "watching out" for. That is: if they were previously defined in the code, I need to be able operate on their values.
var a = 'foo'; // only a gets defined
// ...more code here... IMPORTANT: I can only control what comes BELOW this line!
var target = 'exmple.com/?';
var gets = ['a', 'b', 'c']; // these are the names of the variables I want to check for
gets.forEach(function(element) { // checking each one
if(typeof element !== 'undefined') { // if it's previously defined
target += "&"+element+"="+eval(element); // add `&a=foo` to target
}
});
alert(target);
I'd like the alert to be printing example.com/?&a=foo
I've seen the tons of other answers not to use the eval function, and I have tried window[element] in place without success. How would it be best to do this without having to write an if/else for every variable I want to check?
Assuming you can't do otherwise and everything lives in the global scope, you could do without resorting to using eval(). (I'm pretty sure there must be some valid use cases for eval but I don't think this is one is one of them.)
Since you shouldn't trust the content of these variables you shouldn't be using eval. What if your customer options get compromised? (Or simply your customer doesn't know what they're doing.)
var css_color = 'tweet(document.cookie)';
You can simply leverage the fact that the variables will be accessible from the global scope:
const serialize_options = (...vars) =>
vars
.filter(v => typeof this[v] !== 'undefined')
.map(v => `${v}=${this[v]}`)
.join('&');
console.log(serialize_options('a'));
console.log(serialize_options('a', 'b'));
console.log(serialize_options('a', 'b', 'c'));
console.log(serialize_options('a', 'x', 'y'));
<script>
var a = '10';
var b = '20';
var c = '30';
</script>
The answer to this kind of question is almost always "You're thinking about the problem wrong.", as is the case here.
You make the assumption that this should be done with variables and that backs you into the corner of only being able to use eval() to get out of that corner. I understand that the customer may have asked for regular variables, but if I were a house builder and the customer asked me to build a house out of marshmallow, I'd say "no", that's not the way to do it.
The solution is to use an object with keys and values from the start, which allows you to use array indexing syntax later, instead of eval.
// Keep the items you need to check in an object
var obj = {
a:'foo' // only a gets defined
}
var target = 'exmple.com/?';
var gets = ['a', 'b', 'c'];
// Check each array element
gets.forEach(function(element) {
// Objects can use array indexing syntax where a string is passed as the index
// because objects actually have keys, rather than numeric indexes
if(obj[element]) { // if it's previously defined
target += "&" + element + "=" + obj[element]; // add `&a=foo` to target
}
});
alert(target);

Is array.push a form of reassignment?

I'm working in a project with several javascript files and part of what I'm doing right now is both migrating existing code to use newer ES6+ features as well as making sure we're abiding by the AirBnB Eslint Rules.
So, given that context, this is the specific situation:
let meta = [a.platform];
And right below that:
meta.push(a.browserName ? a.browserName : 'any');
So now the linter is giving me a warning: 'meta is never reassigned. Use const instead'.
I understand that meta = somethingNew would be reassigning the variable. But in this case, isn't this variable also something different than what it used to be when it was created?
or, to make it even more clear
Can I use a const to define an array that will receive new items? If not, why?
Also, if not: why is the linter throwing a warning?
The only thing you have to know is that const has nothing to do with immutability. const simply allows you to prevent reassignment, which means that you cannot do that:
// OK
const foo = '';
const bar = [];
const baz = {};
// WTF are we doing!?
foo = 'Foo';
bar = ['Bar'];
baz = {baz: 'Baz'};
However, in JavaScript, object values are mutable ; contrary to primitive values that are immutable. So if you put a string in a const, you will not be able to modify it at all, even with String.prototype methods (which return new strings).
const str = 'Lorem ipsum';
console.log(str.slice(6)); // This is actually a new string...
console.log(str); // The original string has not been modified!
It is quite different with arrays or object literals, though:
const arr = [];
const obj = {};
arr.push('Foo');
arr.push('Bar');
obj.foo = 'Foo';
obj.bar = 'Bar';
console.log(arr); // Modified!
console.log(obj); // Modified!
At this point, it should be clear: the linter shows this warning because, indeed, meta is never reassigned... A mutation is not a reassignment.
meta.push() doesn't reassign the variable, it just modifies the array that the variable refers to -- it's still the same array, but with different contents. So you can use const for the variable declaration, since you never make it refer to a different array.
The same is true if you assign to array elements. This is OK:
const meta = [a.platform];
meta[1] = somethingNew;
The second assignment doesn't change meta, it changes the array.

Change the value of an evaluated var in JavaScript

I have a var containing a JSON string. (Here I won't parse it because it is not the main problem)
var variable = '{"name":"Johnny Appleseed"}';
var string = "variable";
I evaluate the string.
var evaluatedstring = eval(string);
Now I would like to delete the value of the var variable.
variable = undefined;
If I do:
console.log(evaluatedstring)
It works fine and returns me the JSON string as:
{"name":"Johnny Appleseed"}
But if I do:
evaluatedstring = undefined;
Of course it doesn't work.
eval(string) = undefined;
doesn't work either. (Returns the error Uncaught ReferenceError: Invalid left-hand side in assignment)
How can I delete the content that via the evaluated var?
No jQuery, please.
On Chrome 50+ so not a problem with the browser.
If you're working in the browser: Global variables in JavaScript are created as properties of the window object. Therefore, what you're trying to do can be done like this:
var variable = 'some variable';
var variableName = 'variable';
window[variableName] = undefined;
variable === undefined // Will now be true
However, just the fact that this is possible doesn't mean it's a good idea - in fact, it's just the opposite, it's bad style and will probably confuse anyone looking at your program to no end. If this is really necessary for your algorithm to work, you might want to rethink your data architecture. If this is just a scoping issue (you don't want that variable to pollute your global namespace), an IIFE will likely solve your problem.

Get function name in 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];
};

Categories

Resources