I'd really like to track variables without switching between Firebug console windows or clicking around so much, so I want to draw a runtime viewer of variable names and their corresponding values that will display on the page of the app I am building.
I'd like to two functions, show(variableName) and freeze(variableName). They will output both the variable's value and the name of the variable or object as a literal string which will serve as the text label in the viewer. freeze(variableName) is the same as show(variableName) except with a setTimeOut timer for tracking loops.
I'm sure I'm missing something basic, but I haven't found out a way to get the string that comprises the name of a value programmatically so I can use it as a label. I guess I could create the table with hardcoded labels prior to runtime and just populate it with values at runtime, but I really want to generate the table dynamically so it only has those variables I specifically want to show or freeze. Simple functions:
foo1 = "Rock";
show(foo1);
foo2 = "Paper";
show(foo2);
foo3 = "Scissors";
show(foo3);
should output this via getElementById('viewer-table'):
<table>\<tr><td>foo1</td><td>Rock</td></tr><tr><td>foo2</td><td>Paper</td></tr><tr><td>foo3</td><td>Scissors</td></tr></table>
I've tried this solution:
How to convert variable name to string in JavaScript?
and eval() but it's not working for me...I dunno, shouldn't this be easy? Getting frustrated...
Thanks,
motorhobo
I am not sure you can actually get the "name" of the variable that is being passed into a function for two reasons:
1) The variable is just an identifier. In fact, you could have multiple identifiers reference the exact same object. You are (generally) passing that reference, not any actual object.
2) The show/freeze function is going to stomp on the identifier name, either through named arguments in the function declaration or by referencing them through the arguments array.
I was trying to think if there was some clever way to use the arguments.callee or the stack property on an exception in Firefox... but I can't see anything that would expose the arguments as you desire.
What I would recommend is to simply add the name of the variable and its value to a simple object, and call one of the various jsDump methods (I prefer the one in QUnit):
function show(o) {
document.getElementById("viewer-table").innerHTML = QUnit.jsDump(o);
}
// actually use the method
show({"foo1":foo1});
There's no easy way to solve this as the called function simply doesn't know the original name of the variable. You couldn't solve this with reflection even (esp. in javascript) so you'll have to pass the name of the variable to the function too. To follow the link you posted:
function show(varObject)
{
for(name in varObject)
{
alert(name + ": " + varObject[name]);
// save both name and reference to the variable to a local "to observe array"
}
}
And call it with
var test = "xxx";
show({'test' : test});
Within the for loop you could add easy variable to a monitor array and update your gui in fixed time intervalls (you can't be notifed when a signle variable changes it's value. You need some kind of global monitor/observer which exactly you're trying to create).
Related
In the following code, I would expect the output to be "text something different" but instead it is "text something".
var dynamic = "something";
var thistext = "text " + dynamic;
dynamic = "something different";
console.log(thistext);
Changing the variable "dynamic" after declaring the variable "thistext", which contains it, does not change the value of "dynamic" within the "thistext".
I am sure this is something basic, but I think I do not know this rule or the best way to avoid this situation.
A Jsfiddle:
https://jsfiddle.net/k5wwpvgt/
Why when a variable is used within another variable, its value is fixed to first declaration?
You are not "using a variable within another variable". You are using a variable in an expression, the evaluated result of which happens to be being assigned to another variable. Expressions are evaluated when they are encountered, with the current values of any variables within them. There's no particular word for this behavior, since it is so fundamental to JS (and all other imperative/procedural languages).
Expressions are not dynamic definitions of calculations which are magically kept updated when their inputs change, much less magically updating variables to which the expression happened to have been assigned in the past. There is a word for such dynamic definitions of calculations: they are called functions. If you want some calculation to be dynamically redone when its inputs change, then write it as a function and call it when you need to recalculate, and if you want to (re-)assign the result of the invocation (the return value) to a variable, then do so.
Is there a way to contain a reference to a variable within another variable, and not the value of the variable when the assignment was evaluated?
Again, you're confusing variables and expressions and possibly functions. A variable is merely a box, referring to some value. It maintains no record of when or how it was assigned to, or what expression was used to calculate the value being assigned to it, nor does it have any means of automatically updating itself. Being a box, a variable cannot "contain a reference to another variable".
the best way to avoid this situation.
This is not a "situation" to be "avoided". It is the basic behavior of JavaScript.
Indeed, as others pointed out, this is expected behaviour; to do what you want, you could use a function:
var dynamic = "something";
var thistext = () => "text " + dynamic;
dynamic = "something different";
console.log(thistext());
Mind the diferences! Now thistext is a function, you must call it with (), and it gets evaluated every time.
thistext does not "contain" the variable dynamic, it contains the contents of that variable as it was at the time the expression was evaluated.
When browser will compile your javascript it will look something like
var dynamic = undefined;
var thisText = undefined;
dynamic = "something";
thistext = "text " + dynamic;
dynamic = "something different";
console.log(thistext);
when you are logging the value, you are just logging the value of thisText, which is populated when the value of dynamic is "something".
If you do the same operation after changing dynamic value you will see your desired result.
Hope this helps.
I"m trying to teach my self coding for some mapping work, and I cannot seem to wrap my head around this.
I have a JavaScript function that is called from a button:
This code connects my button using DOJO:
on(dom.byId("metro"), "change", updateLayerVisibility);
The following code correctly turns my layer off (metro is defined elsewhere)
function updateLayerVisibility(){
metro.setVisibility(false);
}
However if i try to use a variable I get an error that "test.setvisiblity is not a function"
function updateLayerVisibility(){
var test = "metro";
test.setVisibility(false);
}
So my question is what is the difference between these two? why isn't "metro" substituted for "test"? If its because the variable is a string, what should it be converted to.
Thanks (and sorry for the strange question)
In your above example, test is just a string and strings don't have a method named setVisibility. However a metro object (apparently) does.
The methods available to strings can be seen here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Methods
metro is an identifier. In that context it is a variable. It will have a value, in this case, that value is an object with a property setVisibility that has (in turn) a value that is a function.
test is also an identifier and a variable. It has a value, which is the string "metro". The string has no connection to the variable metro and it doesn't have a setVisibility property.
The key part of your question is where you say "metro is defined elsewhere". As already suggested by others, your metro object is not just a string with a value (as your test object is) but a reference to a particular type of object which has particular functions such as setVisibility.
I think I see what you want to do: programmatically turn individual layers on and off. If you know the layer ID then you can get a reference to a layer using:
var layer = map.getLayer(id);
(where map is your reference to the ArcGIS map object and id is the string name of the layer to return. So if you had a layer with the id "metro" you would get it with:
var layer = map.getLayer("metro");
Here you can substitute the string passed in to the getLayer method for any other string value that represents the id of a layer you want.
Once you've got your layer object you can then set it's visibility in the same way as you were with the metro layer reference:
layer.setVisibility(false);
Hope this helps!
I am using code lines like the following in order to fetch data from an intranet website:
util.setProp(obj, "firstNameOld", $(msg).find('#fname_a').text());
Now I have another function in the same file where I want to use the above again, resp. the value of that object - currently I am hard-coding this ('Test') for test purposes:
util.setProp(obj, "firstNameNew", 'Test');
How can I pass the value from the firstNameOld object in one function to the firstNameNew object in another function ? If a solution with global variables is better here than this would work as well.
Many thanks for any help with this, Tim.
I've never used the framework that includes util But I imagine that if there is a setProp() then there has to be a getProp() or something similar.
If so, you could do something like
util.setProp(obj, "firstNameNew", util.getProp(obj, "firstNameOld"));
This also relies on the assumption that you want to copy from two properties in the same object.
If not, then pass the desired source object in the getProp() call.
My guess is that functions (or properties) are called "firstNameOld" and "firstNameNew", so the first time you get it from selector, second time you want to do the same.
Try to use the local variable like that:
var text = $(msg).find('#fname_a').text();
//
util.setProp(obj, "firstNameOld", text);
//
util.setProp(obj, "firstNameNew", text);
I have a variable called jsonAllSignOffs that is created by a .NET JSON service and sent to the client. It is essentially a struct containing various arrays. The values of these arrays are arranged such that if you took the nth element of each array, all together that would be the collected properties of the nth Sign Off. Obviously a list of Sign Off objects containing these properties would be better, but unfortunately this is a legacy application and changing it's architecture in this manner is out of scope.
What I'm trying to do is create a variable called jsonUserSignOffs that is essentially a subset of jsonAllSignOffs with all the same properties. However jsonAllSignOffs is not a type that I can instantiate. I figured declaring a variable and assuming the properties by assigning into them would "build" the object, but apparently that's not the case.
var jsonUserSignOffs;
jsonUserSignOffs.isAuthor = jsonAllSignOffs.isAuthor; //error jsonUserSignOffs is undefined
Since javascript doesn't support classes and is pretty lax with variables I figured the only way to create a struct like jsonAllSignOffs was to declare the variable and assign values to it's properties. I know these properties are not defined anywhere, but I thought assigning values to them would instantiate them at the same time. I come from a C# background where I would use a class. Javascript is less familiar to me, and I'm unclear on how to proceed.
Try this
var jsonUserSignOffs = {}; //creates an empty object using object literal notation
jsonUserSignOffs.isAuthor = jsonAllSignOffs.isAuthor;
OR:
var jsonUserSignOffs = {
isAuthor: jsonAllSignOffs.isAuthor
};
Im sure this must have been asked before but I can't find an example on SO.
I have a JSON string that starts out life as something like this:
{"model":"14","imgsize":"890","selection":{"SC":"BC","PC":"AC"},"changed":{"PC":"AC"}}
The string needs to be changed on user input such that "selection" records all the input the user has click on and "changed" is the last thing the user clicks on.
So I have a function that reads the JSON string from a textarea, modifies it dependant on what the user has selected (node and value) and then writes it back to the text area for debugging.
function changeJSON(node, value) {
json = JSON.parse($('#json').val());
json.selection[node] = value;
delete json.changed;
json.changed = {node:value};
$('#json').val(JSON.stringify(json));
}
"selection" works nicely but "changed" updates to the literal variable name I pass it (in this case node) I.e. if I called the function with changeJSON("BC","HC") the JSON string becomes:
{"model":"14","imgsize":"890","selection":{"SC":"BC","PC":"AC","BC":"HC"},"changed":{"node":"HC"}}
I understand what javascript is trying to do but I want the changed element to be what my variable contains i.e.
,"changed":{"BC","HC"}
and not
,"changed":{"node","HC"}
I'd love someone to tell me what I am doing wrong!?
EDIT
Solved - see below for Quentin explanation as to why and my answer for the code changes necessary - hope it helps others.
I don't think this is the same question, mine is why the literal variable name is used rather than the contents of the variable
The question referenced explains how to resolve the issue, but since you are asking for an explanation.
A variable name is a JavaScript identifier.
A property name in object literal syntax is also a JavaScript identifier (although you can use a string literal instead).
Since an identifier cannot be both a variable and a property name at the same time, you cannot use variables for property names in object literal syntax.
You have to, as described in the referenced question, create the object and then use the variable in square bracket notation.
The solution, as Quentin suggested is to create th object first i.e.
delete json.changed;
json.changed = {};
json.changed[node] = value;