I have a list of variables:
subcatlist1 = 'aa';
subcatlist2 = 'bb';
subcatlist3 = 'cc';
What i would like to do, is insert the value of a given variable from the option options, into an element, but the 'number' of the variable (ie, 1, 2 or 3) is itself coming in as a variable, say itemNumber.
What I would like to do is:
$(element).html(subcatlist+ itemNumber);
... Which would give the value of aa for itemNumber = 1
The error that I am getting is:
ReferenceError: subcatlist is not defined - which make sense, because the variable subcatlist doesn't exist - only subcatlist1, subcatlist2, subcatlist3 exist.
Do how can i concatenate the subcatlist+ itemNumber to get a variable that i can use, as subcatlist1 etc?
Thanks
Use object instead of variable is better approach in your context,Because you concadenate with variable is wrong.
var subcatlist = {1:"aa",2:"bb",3:"cc"}
$(element).html(subcatlist[itemNumber]);
Updated
The solution is to access the needed variable as a property of the containing object.
If defined in the global scope using var , in javascript the value is assigned as a property of the global object, and it can be accessed using the self explanatory keyword globalThis
In JavaScript, there's always a global object defined. In a web browser, when scripts create global variables defined with the var keyword, they're created as members of the global object. (In Node.js this is not the case.)
var subcatlist1 = 'aa';
var subcatlist2 = 'bb';
var subcatlist3 = 'cc';
var itemNumber = parseInt(Math.random() * 3) + 1
$('#test').html(globalThis['subcatlist' + itemNumber])
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="test">
See also "Variable" variables in JavaScript
Original answer
If having a list of variables is mandatory you could use eval() like this:
$(element).html(eval("subcatlist"+ itemNumber));
eval can be harmful and should be avoided in most cases
Related
Can anyone please explain why we CAN assign a value without declaring it first. To my understanding we would need to declare a variable first (var visitorsName = prompt("Input your name: "). What is a visitorName if not variable? Thank you so much!
visitor_name = prompt("Input your name : ");
if(visitor_name !=null && visitor_name != ""){
alert("Your name is: " + visitor_name);
} else {
alert("No Name User")
}
When javascript was created, it was expected to be used for small scripts and often by novice programmers. As a result, it was designed to tolerate some sloppy coding practices. One of the ways it does this is that if you fail to declare your variable, it will create a global variable for you.
When this line runs:
visitor_name = prompt("Input your name : ");
Javascript will create a property on the window object named visitor_name. And later on, any time you refer to visitor_name, since there's no other variable with that name, it will access window.visitor_name
I recommend you avoid using this "feature" of javascript, and just declare your variables explicitly.
Javascript variables are loosely typed, which means you can assign any type of value to a variable.
Scope of the variables declared without var keyword become global irrespective of where it is declared. Global variables can be accessed from anywhere in the web page
x = 1;
console.log(x);
x = "one";
console.log(x);
However it is not recommended to declare a variable without it's data type because it messes with the scope of other variables and may change the value of some global variable.
function tidsbestilling() {
var valgtDato = document.getElementById('datepicker').value
console.log(valgtDato)
var getDato = "D" + valgtDato.substring(0, 2) + valgtDato.substring(3, 5) + valgtDato.substring(6, 10)
console.log(getDato);
}
console.log(D31102019);
Im trying to access a const called D31102019 from another js file. The variable is date specific, so if the user chooses another date(ex. 30-10-2019), i want to be accessing the variable D30102019 instead. How can i make the "getDato" variable(currently defined as "D31102019"), into something i can actually use to access the const from the other file?
If it is a global variable it will be in the scope of window, you can access it using:
var variableName = 'D31102019';
window[variableName];
Or in your case
window[tidsbestilling()]
But you have to return the result from your function:
function tidsbestilling() {
var valgtDato = document.getElementById('datepicker').value;
var getDato = "D" + valgtDato.substring(0, 2) + valgtDato.substring(3, 5) + valgtDato.substring(6, 10);
return getDato;
}
This declaration creates a constant whose scope can be either global
or local to the block in which it is declared. Global constants do not
become properties of the window object, unlike var variables. An
initializer for a constant is required; that is, you must specify its
value in the same statement in which it's declared (which makes sense,
given that it can't be changed later)
If you choose using const which comes in the next version of javascript then you are supposed to export the constant from one file and then import that constant whereever you require using es6 module system. If you go with es5 then var is fine. But it is always a good idea to make your code modular avoiding globals.
The old style JavaScript var declaration outside of a closure is global (top-level scope) and can be accessed in a browser from the window object. For example, the declaration var x = 3; can be accessed with window['x'].
How do you similarly access a const or let declaration given the name (string) of the declaration?
var x = 3;
const y = 7;
let z = 21;
console.log('x = ' + window['x']); //x = 3
console.log('y = ' + window['y']); //y = undefined
console.log('z = ' + window['z']); //z = undefined
For the above example, how do you get the values 7 and 21 for "y" and "z" instead of undefined?
Fiddle with the code:
https://jsfiddle.net/g78ah6we/
Edits (notes added for clarity):
1. While not typical, there are use cases, such as from within a library, that it's necessary to access a declaration based only on the name of the declaration.
2. Only read access is needed (none of the declarations will be modified).
3. The window object is mentioned just to show the old way, but this question is not actually about using the window object (or the global object).
Using indirect calls to eval
Accessing global const and let definitions can be done using an indirect call to eval. That is make eval the result of a comma separated expression or assign it to a variable first. If the syntactic access is not directly to the built-in eval function it's an indirect access, and indirect access executes in global scope.
You can also set global let variables by building script to perform the setting operation.
"use strict";
let myVar = "global variable myVar";
console.log( myVar);
(function myLibrary() {
const myVar = "local variable myVar";
const indirectEval = eval;
var varName = "myVar";
console.log( eval(varName)); // direct call uses local scope
console.log( indirectEval(varName)); // indirect call uses global scope
var result = "\"updated global variable even though shadowed\"";
var js = varName + '=' + result;
indirectEval(js);
// but trying to define a new let variable doesn't attach to global scope
var js2 ='let letVar2 = "let variable two"';
indirectEval( js2);
})();
console.log( myVar)
console.log( "letVar2: " + typeof letVar2);
What you can't do is add a let or const variable to global scope using an indirect call to eval: they are block level declarations and the code eval evaluates is considered a block - so the declarations are discarded when (indirect call to ) eval returns.
PS. This is a technical answer. And yes, I have heard that "eval is evil" before, one or three times.
For read access only using hard-coded variable name strings (to prevent code insertion) you could use the pattern:
(0,eval)("identifierString");
as for example:
var x = 3;
const y = 7;
let z = 21;
{
const y = "shadow"
let z = 42;
console.log('x = ' + (0,eval)('x')); //x = 3
console.log('y = ' + (0,eval)('y')); //y = 7
console.log('z = ' + (0,eval)('z')); //z = 21
}
Indirect vs direct calls to eval
A direct call to eval only obtains the values of global variables that have not been shadowed in function scope of the call. This may restrict choice of variable names, or where the call can be made from, within the library.
An indirect call executes in global scope and can obtain the value of global variables irrespective of name shadowing within the library.
Creating a new Function object from source text, and calling it, may provide be an alternative to using an indirect call to eval in a web page. However the difference is largely semantic rather than one being better than the other.
Issues
If the global variable name (var, let, const or class identifier) comes from user input it really should be checked for validity (not all that easy) or at least accessed within a try/catch block to trap used of undeclared identifiers or use of name declarations before initialization.
Personally I would recommend finding alternatives to using global variable name strings in general. Providing a static name space object on the library (e.g. myLibrary.data) and processing string values that are property names of the object, or including option object parameters in library calls, come to mind.
Both let and const are block scoped.
In contrast, the variable declarations without var keyword creates variables in the outermost functional scope bubble. In browsers, the outermost functional scope is controlled by the window object.
What the window object doesn't control is the outermost block scope.
If your code doesn't work without being able to access variables in the window[nn] pattern, there definitely is a design issue in it.
I've marked traktor53's answer as accepted and upvoted it because it contains the technical core of the solution.
In case it's helpful for anyone, here's a solution wrapped up into a function that prevents executing code in the declaration.
var x = 3;
const y = 7;
let z = 21;
const malware = 'alert("Game over.");';
function getDeclaration(name) {
var identifierPattern = /^[_$a-zA-Z][_$a-zA-Z0-9]*$/;
var topLevelGet = (null, eval);
return identifierPattern.test(name) && topLevelGet('typeof ' + name) === 'number' ?
topLevelGet(name) : null;
}
console.log(getDeclaration('x')); //output: 3
console.log(getDeclaration('y')); //output: 7
console.log(getDeclaration('z')); //output: 21
console.log(getDeclaration('bogus')); //output: null
console.log(getDeclaration('malware')); //output: null
console.log(getDeclaration('if')); //EXCEPTION: unexpected keyword
Notes:
Be aware that the identifierPattern regex is very simplistic (does not handle all valid characters and trips up on reserved words... as traktor53 pointed out, "This is more complicated than you might think").
Change 'number' to 'object' or whatever is appropriate for your needs (for simplicity in the original question I used examples with numbers, but my real use case actually looks for objects).
Fiddle with the code:
https://jsfiddle.net/g78ah6we/6/
This is a serious question, It has been nagging me for a while. In JavaScript you can declare a variable which has no type. It's type is often dynamic, depends on further value assigned to it.
e.g
var text;
typeof(text); //undefined
text = 'someText';
typeof(text); //string
So as we know that Javascript can dynamically change variable's type why these assignments are invalid then?
e.g
var someObj;
someObj.a = 'hello world';
console.log(someObj) //TypeError
var someTable;
someTable[0] = 'hello world';
console.log(someTable[0]) //TypeError
where this problem can be fixed just by adding definition to variable declaration:
var someObj = {};
var someTable = [];
I'd expect a good explanation of this problem. Thanks for answers.
There's a big difference between declaration and initialisation of variables.
When you declare a variable without initializing it with a value, its type will be undefined, so when you will try to call it or access it, it will give undefined, because simply there were no value defined for the variable.
That's why it should be initialized:
var someObj = {};
var someTable = [];
So you can treat it as a string, an object or an array according its initialized value.
Documentation:
Please take a look at variables MDN Reference for further reading, where it says:
A var statement declares variables that are scoped to the running execution context’s VariableEnvironment. Var variables are created when their containing Lexical Environment is instantiated and are initialized to undefined when created. [...] A variable defined by a VariableDeclaration with an Initializer is assigned the value of its Initializer’s AssignmentExpression when the VariableDeclaration is executed, not when the variable is created.
You're getting confused about where the error is thrown. In your first example:
var someObj;
someObj.a = 'hello world'; // the error is thrown here
That error is thrown because someObj is undefined (not undeclared). So, you can't access the property a on undefined.
The same explanation applies for your second example:
var someTable;
someTable[0] = 'hello world'; // the error is thrown here
You're trying to access index 0 of undefined.
The reason that defining them as {} and [], respectively, fixes your issue, is that you are then accessing property a of {} and index 0 of [].
1) Data types in Javascript are not dynamic, they are mutable. This means that depending on kind of operation you are applying to them they can change from being something into another thing (e.g. a number can become a string doing something like this: 4 + 'a').
2) The "error" is a consequence of having a variable not initialized. In Javascript when you are doing this:var something = 'a'
you are doing two operations, a declaration, and an assignment. If you don't do the assignment and you try to access to a property of the object you have declared it will throw an error. In your case, you are declaring a variable but not initializing it to the "compiler" can't access the "a" property or the position 1 because it is of type undefined.
This question already has answers here:
Use dynamic variable names in JavaScript
(19 answers)
Closed 9 years ago.
Is it possible to set a variable by concatenating two strings together to form the name?
If at all possible I'd like to determine what variable to set based on the class names of the objects that the user clicks. I know I can hard code a bunch of if/else if statements, but it would be really cool if I could reference the variables indirectly. I was thinking something like this:
var owner_read;
var group_read;
function setVariableIndirectly(object){
var second = object.className; // returns "read"
var first = object.parentElement.className; // returns "group"
first + "_" + second = "set this as the new variable";
}
Is there any way of doing this??
EDIT:
Here's the html that the data is coming in from.
<p class="owner">
<span class="read" onclick="permissionClick(this)">r</span>
<span class="write" onclick="permissionClick(this)">w</span>
<span class="execute" onclick="permissionClick(this)">x</span>
</p>
This is possible but you have to be wary of context and scope.
1. To set variable with global scope in browser environment:
window[str1 + str2] = value
2. To set variable with global scope in node environment:
global[str1 + str2] = value
3. Within a closure and scoped within that closure:
this[str1 + str2] = value
Within the closure, global and window will still set the global. Note that if you are within a function that is being called, 'this' could refer to another object.
It's not clear exactly what you're trying to accomplish, but you can access variables by name as properties of an object.
// this is the container to hold your named variables
// (which will be properties of this object)
var container = {};
function setVariableIndirectly(obj){
var second = obj.className; // returns "read"
var first = obj.parentNode.className; // returns "group"
// this is how you access a property of an object
// using a string as the property name
container[first + "_" + second] = "set this as the new variable";
// in your example container["read_group"] would now be set
}
It's probably better to put your variables on your own container object as shown above, but you can also access global variables via properties on the window object.
You can set a global variable this way:
window[first + "_" + second] = "set this as the new variable";
and access it as:
console.log(group_read);