Change a variable that's name is in another variable - javascript

I've got a bit of a problem here. I've got the following code declaring two variables:
var anawesomevariable = "hello world";
var variabletwo = "anawesomevariable";
As you can see, the second variable's contents are the same as the name of the first variable. My problem: I want to change the first variable using the contents of variabletwo. So in other words, I want to say "Hey Javascript, change the contents of the variable whose name is in variabletwo". Is there any way to do this in Javascript?
P.S. I havn't really explained that clearly, but you get my point (I hope)

You can do
eval(variabletwo + ' = "new value"');
which results in running the code
anawesomevariable = "new value";

If awesomevariable is a global variable you can do this:
window[variabletwo] = 'goodbye world';

You cannot* (and should not) manipulate variables, but it's a piece of cake with properties:
var obj = {anawesomevariable: "hello world"};
var variabletwo = "anawesomevariable";
obj[variabletwo] = whatever
^* don't even think about "eval" here. seriously.

You have a few options. Option 1, which uses eval(), which I discourage, would be simplest, like this
eval(variabletwo + ' = "cool"');
The second option is to declare them as globals, like this
window.anawesomevariable = "hello world";
window.variabletwo = "anawesomevariable"
and then
window[variabletwo]="foo";
However, if you want to keep something in the current scope, declare it in an object, like this
var obj = {anawesomevariable: "hello world"};
var variabletwo = "anawesomevariable";
obj[variabletwo] = "foo";

Related

How to eval variables into local scope object's properties instead of global scope in JavaScript

I have some code return from server like "var myVar = 314;", I would like to create a context object like so var context = {}; and then eval the script "var myVar = 314;" into properties of context, how could I achieve this ?
I have tried the below code, but without success:
var context = {};
eval.call(context, "var myVar = 314;");
EDIT
May be I wasn't clear enough in the first place, the result I expected is: after eval(), I got the properties in the context object, the aim is to avoid global scope population.
For example,
var context = {};
eval.call(context, "var myVar = 314;");
I would expect the result as context.myVar = 314.
Are you able to change the format of the script you get from your server? If so, follow the advice in Aadit's comment and have your server send:
context["myVar"] = 314;
or:
context.myVar = 314;
If you can't change the format, is the script literally as simple as var myVar = 314;?
If it is, try rethinking the approach. Instead of trying to eval() the script in some particular context, parse the script into a form you can work with. For example:
var script = 'var myVar = -314.5;'; // what we get from the server
var match = script.match( /var\s+(\w+)\s*=\s*(-?[\d.]+)\s*;/ );
if( match ) {
// match[1] is 'myVar', match[2] is '-314.5'
context[ match[1] ] = +match[2];
}
console.log( context );
Now context is { myVar: -314.5 }. This code could be run inside a function or anywhere and would work the same.
You could use a similar regular expression for a string variable assignment:
var script = 'var myString = "Test Value";'; // what we get from the server
var match = script.match( /var\s+(\w+)\s*=\s*"([^"]*)"\s*;/ );
if( match ) {
// match[1] is 'myString', match[2] is 'Test Value'
context[ match[1] ] = match[2];
}
console.log( context );
This time, context is { myString: "Test Value" }
This approach could easily be adapted for multiple variables, other data types, etc.

Alternative to using eval()

I've heard a lot of rumblings about how "evil" or even "misunderstood" the eval function is, so I've decided to remove it from my code. The problem is I don't know what to replace it with.
Here's a quick rundown of my current code. I have a series of arrays (just 2 for the example below) declared at the beginning, and then based on a button click one of them gets loaded into a variable that is passed into a function.
Here's some basic HTML
<div class="button" data-name="button1">Button1</div>
<div class="button" data-name="button2">Button2</div>
and the JS (with jQuery)
var butName = null;
var eArray = null;
var button1Logo = ["..path/to/pic1.png","..path/to/pic2.png"];
var button2Logo = ["..path/to/pic3.png","..path/to/pic4.png"];
$(".button").mouseup(function(){
/*give a butName*/
butName = $(this).attr("data-name");
/*give the array from the button*/
eArray = eval(butName + "Logo");
});
Doing it this way assigns the array to the variable and not just a string that says "butnameLogo" which is why I used eval. But I'm looking to get away from that.
I know I can add a new attribute to the html and just retrieve that for the variable but I don't want to add more html when I can possibly do it with JS.
I've also tried making an object with strings loaded into it as seen in this answer: https://stackoverflow.com/a/16038097/1621380 but that resulted in just a string again, and not assigning a variable.
Wondering if you smart people have any better suggestions!
Replace
var button1Logo = ["..path/to/pic1.png","..path/to/pic2.png"];
var button2Logo = ["..path/to/pic3.png","..path/to/pic4.png"];
with an object, where the keys are your button names:
var buttonLogos = {
button1: ["..path/to/pic1.png","..path/to/pic2.png"],
button2: ["..path/to/pic3.png","..path/to/pic4.png"]
};
Then instead of the eval you can simply do
eArray = buttonLogos[butName]
(or buttonLogos[butName + "Logo"] if you want to call the keys button1Logo and button2Logo, but I can't really see the point now that they are nicely contained within a buttonLogos object)
Use an object:
var butName = null;
var buttonsLogos = {
button1: ["..path/to/pic1.png", "..path/to/pic2.png"],
button2: ["..path/to/pic3.png", "..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/*give a butName*/
butName = $(this).attr("data-name");
/*give the array from the button*/
eArray = buttonsLogos[butName];
});
Consider making the data available as properties of an object, then you can control access to the object through scope and only need one (global?) variable for all such data.
If global scope is needed, then:
var dataObj = {
button1Logo: ["..path/to/pic1.png","..path/to/pic2.png"],
button2Logo: ["..path/to/pic3.png","..path/to/pic4.png"]
}
and later:
var eArray = dataObj[this.data-name + 'Logo'];
You may want to call the data object something more meaningful than dataObj though.
The best option is to define an object which holds all our button paths:
var buttons = {
"1": ["..path/to/pic1.png", "..path/to/pic2.png"],
"2": ["..path/to/pic3.png", "..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/* give a butName */
var butName = $(this).attr("data-name");
/* give the array from the button */
var eArray = buttons[butName];
});
If your variables reside in the global scope, you could use the bracket notation to access them:
eArray = window[butName + "Logo"];
Note that this solution is not recommended. The first code sample is much cleaner and more maintainable.
Imagine a situation where you would have to move all the code into a 'deeper' context (!= global context). Nothing would work anymore.
You can do this very nicely with arrays and array indexes. You needn't find and use variable names at all. Even your data- attributes are unnecessary.
var eArray;
var buttonLogos = [
["..path/to/pic1.png","..path/to/pic2.png"],
["..path/to/pic3.png","..path/to/pic4.png"]
];
var buttons = $(".button").mouseup(function(){
var idx = buttons.index(this);
eArray = buttonLogos[idx];
});
The key line in this is buttons.index(this). This method call gets the position of the current element among all the elements matched by $(".button"). We then use this index to select the relevant element from the buttonLogos array.
You're taking a very circuitous route by using eval here.
You'd be much better off doing something like this:
var paths = {
button1: ["..path/to/pic1.png","..path/to/pic2.png"],
button2: ["..path/to/pic3.png","..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/*give the array from the button*/
eArray = paths[$(this).attr("data-name")];
});
eval should only be used if you need to execute code (usually from a 3rd party source), and even that is rare. If you ever find yourself saying "i should use eval here", there's almost definitely a better alternative, and you should try and find it.

In JS,how to get a obj variable's name

like this code
var Obj = function () {}
Obj.prototype.getVarName = function () {
console.log( someFunction() );
}
var obj = new Obj();
obj.getVarName(); //output "obj";
var obj1 = new Obj();
obj1.getVarName(); //output "obj1";
and i don't want to do it in this way
var Obj = function (variableName) {
this.variableName = variableName || "undefined";
}
Obj.prototype.getVarName = function () {
console.log(this.variableName);
}
var obj = new Obj('obj');
obj.getVarName(); //output "obj";
var obj1 = new Obj('obj1');
obj1.getVarName(); //output "obj1";
someone has any idea to do with this problem,thanks.
p.s:I was doing something in somg incorrect way.so I ask this Unanswered question,thanks all guys.
I bing an event to an DOM elem by a class obj's method ,and this obj has somg child class obj,when trigger the event,this varialbe is point to the dom elem,any I don't know how to recognition which obj trigger this event,so i try this way.
But it's a wrong way!So i try it by some other method.I use the call method to change the this variable,and now i solve my problem.
I believe the answer is "it can't be done".
Variable labels aren't meant to be looked at by your code at run-time. They're meant for you, as the program author, to be used at program write-time.
If an Object needs a label that you need to examine and use at run-time you should give it that property to use.
someObject.myName = "someObject"; // if that's what you really want
There's simply no relation from an object to the variable holding it as value.
Because there can be more than one variable.
var obj = new Obj();
var obj2 = obj;
obj2.getVarName(); // what do you want ?
That's one of the basis of the concept of variable in probably all programming languages. You won't change that. if you want your objects to have a name, the solution is to give them a name, not using the variable names.
What dystroy and Genia S. said.
Your code smells BAD. Why are you trying to do this?
The way you don't want to do it actually looks like the best option, i.e. create an object with a name field.

Get variable names with JavaScript

I want to create a log function where I can insert variable names like this:
var a = '123',
b = 'abc';
log([a, b]);
And the result should look like this in the console.log
a: 123
b: abc
Get the value of the variable is no problems but how do I get the variable names? The function should be generic so I can't always assume that the scope is window.
so the argument is an array of variables? then no, there is no way to get the original variable name once it is passed that way. in the receiving end, they just look like:
["123","abc"];
and nothing more
you could provide the function the names of the variables and the scope they are in, like:
function log(arr,scope){
for(var i=0;i<arr.length;i++){
console.log(arr[i]+':'scope[arr[i]]);
}
}
however, this runs into the problem if you can give the scope also. there are a lot of issues of what this is in certain areas of code:
for nonstrict functions, this is window
for strict functions, this is undefined
for constructor functions, this is the constructed object
within an object literal, this is the immediate enclosing object
so you can't rely on passing this as a scope. unless you can provide the scope, this is another dead end.
if you pass them as an object, then you can iterate through the object and its "keys" and not the original variable names. however, this is more damage than cure in this case.
I know you want to save some keystrokes. Me too. However, I usually log the variable name and values much like others here have already suggested.
console.log({a:a, b:b});
If you really prefer the format that you already illustrated, then you can do it like this:
function log(o) {
var key;
for (key in o) {
console.log(key + ":", o[key]);
}
}
var a = '1243';
var b = 'qwre';
log({
a:a,
b:b
});
Either way, you'd need to include the variable name in your logging request if you want to see it. Like Gareth said, seeing the variable names from inside the called function is not an option.
Something like this would do what you're looking for:
function log(logDict) {
for (var item in logDict) {
console.log(item + ": " + logDict[item]);
}
}
function logSomeStuff() {
var dict = {};
dict.a = "123";
dict.b = "abc";
log(dict);
}
logSomeStuff();
Don't know if this would really work in JS... but you can use a Object, in which you can store the name and the value:
function MyLogObject(name, value) {
this.name = name;
this.value = value;
}
var log = [];
log.push(new MyLogObject('a', '123'));
log.push(new MyLogObject('b', 'abc'));
for each (var item in log) {
if (item.value != undefined)
alert(item.name + "/" + item.value);
}
Then you can loop thru this Object and you can get the name and the value
You can't access the variable names using an Array. What you could do is use objects or pass the variable names as a String:
var x = 7;
var y = 8;
function logVars(arr){
for(var i = 0; i < arr.length; i++){
alert(arr[i] + " = " + window[arr[i]]);
}
}
logVars(["x","y"]);
I had a somewhat similar problem, but for different reasons.
The best solution I could find was:
MyArray = ["zero","one","two","three","four","five"];
MyArray.name="MyArray";
So if:
x=MyArray.name;
Then:
X=="MyArray"
Like I said, it suited my needs, but not sure HOW this will work for you.
I feel silly that I even needed it, but I did.
test this.
var variableA="valor01"; <br>
var variableB="valor02";
var NamevariableA=eval('("variableA")');<br>
var NamevariableB=eval('("variableB")');<br>
console.log(NamevariableA,NamevariableB);
atte.
Manuel Retamozo Arrué

Global var in JavaScript

This is annoying me.
I'm setting an array in beginning of the doc:
var idPartner;
var myar = new Array();
myar[0] = "http://example.com/"+idPartner;
And I'm getting a number over the address, which is the id of partner. Great. But I'm trying to set it without success:
$.address.change(function(event) {
idPartner = 3;
alert(idPartner);
}
Ok. The alert is giving me the right number, but isn't setting it.
What's wrong?
Changing the value of the variable does not re-set the values within the array. That is just something javascript can't do automatically. You would have to re-generate the array for it to have the new id. Could you add the id to the value where you use the array instead of pre-setting the values in the array containing the id?
Edit: For example, you would do:
var myArray = [];
var myId = 0;
myArray[0] = "http://foo.com/id/";
and when you need to use a value from the array, you would do this:
var theVal = myArray[0] + myId;
Try this:
var myvar = ["http://site.com/"];
$.address.change(function(event) {
myvar[1] = 3;
}
then use myvar.join () where you need the full url.
The problem here is that at the line
myar[0] = "http://site.com/"+idPartner;
..you perform a string concatenation, meaning you copy the resulting string into the array at index position 0.
Hence, when later setting idPartnerit won't have any effect on the previously copied string. To avoid such effect you can either always construct the string again when the idPartnervariable updates or you create an object and you evaluate it when you need it like...
var MyObject = function(){
this.idPartner = 0; //default value
};
MyObject.prototype.getUrl = function(){
return "http://site.com/" + this.idPartner;
};
In this way you could use it like
var myGlblUrlObj = new MyObject();
$.address.change(function(event){
myGlblUrlObj.idPartner = ... /setting it here
});
at some later point you can then always get the correct url using
myGlblUrlObj.getUrl();
Now obviously it depends on the complexity of your situation. Maybe the suggested array solution might work as well, although I prefer having it encapsulated somewhere in an object for better reusability.
myar[0] = "http://site.com/" + idPartner;
After this line, myar[0] = "http://site.com/undefined" and it has nothing to do with the variable idPartner no more.
So, after that changing the value of idPartner will affect the value of myar[0].
You need to change the value of myar[0] itself.

Categories