Access an element in an object with a dynamic name - javascript

How can I access a element if the name is based on a concatenated value of a string and a number ? I am using twilio and they don't store images not in an array but return a flat file which returns a new element name for each which looks like MediaUrl0, MediaUrl1, MediaUrl2 and so on. Also there is a NumMedia field which would be for 3 attachments 3.
so I use the following
if ( message.NumMedia > 0) {
let i
for (i=0; i < message.NumMedia; i++) {
console.log(`message.MediaUrl${i}`)
}
}
but that does not provide me the actual value but a string of MediaUrl0 since it is not an array I can't use message.MediaUrl[i]

What Jeremy said. Originally you were creating a template string by having the back-tick come before the object that contained the property you were attempting to access. You can't use dot notation obj.prop when accessing properties dynamically.
for (i=0; i < message.NumMedia; i++) {
console.log(message[`MediaUrl${i}`])
}}

Related

Why indexOf can find the index of my object inside array of same class objects?

I'm doing a study of how javascript objects and its operations works and I found this one that I cannot explain. I'm attaching some code:
// first I create an object
var n = new Object ()
var array_obj = []
// now I create 6 more object of the same class and push it into the array
for ( var i = 0; i < 6; i++) {
var newobj = new Object()
array_obj.push( newobj )
}
// finally I push my first object into it
array_obj.push( n )
console.log( array_obj.indexOf( n ) ) // output -> 6
At first I thought It could be related to the === that indexOf performs, but after testing with a custom function I found that the single comparation also works ( == ).
Why is this happening? How does it works?
PS: Custom function
findObject( n )
function findObject ( object ) {
for ( var i = 0; i < array_obj.length; i++ ) {
if ( object === array_obj[i] ) { // same happens if "==" is used instead
console.log( i )
}
}
}
First thing you gotta know about Objects (in javascript) is that they are assigned by REFERENCE and NOT by value. With that in mind, every time you declare a variable and assign it with a javascript object, you are storing the reference to the object's address in memory.
when you use indexOf with javascript objects, you are comparing memory address of the OBJECTS and not from the CLASS. Everytime you use NEW with a class (that returns a javascript object) you are instantiating an object from a specific class and returning the address of the OBJECT that you can store at a variable (in this case, it is 'n').
When you use indexOf(n), the function will search for the memory address of the object stored in 'n' and return it's index location inside the array. The others objects you created inside the loop (even being from the same class) will have an unique memory address for each one.
The reason why it will work with both == and === is that When you use === you will compare objects address to check if they are equal. When you use ==, it will make a type cast before comparing. Example, if you compare a string with a number using ==, it will convert one type into another and then will compare their values.

Get data from array of object and put it to key value

I want to take that._mCon.usa which have array of object's and put the data like key value
in _mUsa object,In the object instance I've name and path ,I try like following and its not working the _mUsa is not filled with data...any idea what im doing wrong here ?
_mUsa{
},
for(var i = 0; i <= that._mCon.usa.length; i++) {
that._mUsa[that._mCon.usa[i][name]] = that._mUsa[that._mCon.usa[i][path]];
}
this is that._mCon.usa with the name and path properties
Object properties are accessed using .propertyname, so it should be:
that._mUsa[that._mCon.usa[i].name] = that._mUsa[that._mCon.usa[i].path];
You use [name] when the property name is dynamic, and name is a variable containing the property name.
You can use [] with a literal string, e.g. ['name'] and ['path'], but there's little point to that; if the property is known, just use the normal dot notation.

Javascript: Change name of an array into a string

Below, I have an array of arrays of objects. I go through looking for my object, and once I find which array it's in, I want to get at and work with that array's name as a string. My guess, was something like Array.name (as it plays out below), but that doesn't work.
ActiveDocument.gaShapesTab1 = new Array(ActiveDocument.Sections["Dashboard"].Shapes["Shape1"],ActiveDocument.Secti‌​ons["Dashboard"].Shapes["Shape2"]);
ActiveDocument.gaShapesTab2 = new Array(ActiveDocument.Sections["Dashboard"].Shapes["Shape3"],ActiveDocument.Secti‌​ons["Dashboard"].Shapes["Shape4"]);
ActiveDocument.gaShapesTab3 = new Array(ActiveDocument.Sections["Dashboard"].Shapes["Shape5"],ActiveDocument.Secti‌​ons["Dashboard"].Shapes["Shape6"]);
ActiveDocument.gaShapeArrays = new Array(gaShapesTab1, gaShapesTab2, gaShapesTab3);
// go through an array of arrays
for(var x=0; x<gaShapeArrays.length; x++)
{
// and go through the objects of each one
for(var y=0; y<gaShapeArrays[x].length; y++)
{
// if "object" is in the array
if(object == gaShapeArrays[x][y])
{
// get "sidetab" from object's array's name
var sidetab = gaShapeArrays[x].name.replace('gaShapes',''); // assumes that shapearrays will have naming convention gaShapesSidetab
// we found it, we can stop now
break;
}
}
}
I'm working in Hyperion Intelligence, so not all Javascript will apply. For instance I don't have access to window or document.
Each array contains a set of shape objects related to a visual tab. This allows me to show or hide or do more complex operation with what's on each tab simply by calling the array of shapes. But, when working with the shapes, themselves, I need to know which tab they're on. I'm trying to work backwards by finding which array they're in.
You don't want to do that.
If you really need to find a value in several arrays and then pull out an identifier, then you want a dictionary, not named variables:
var dictOfArrays = {
'evens': [0,2,4,6,8,10],
'odds': [1,3,5,7,9]
};
This stores the identifier that you seek as data, so you can store that identifier and use it later to retrieve the value if you want:
var whichArrayKey = findMyValuesKey(value, dictOfArrays);
console.log('Value '+value+' is in array keyed '+whichArrayKey);
var matchingArray = dictOfArrays[whichArrayKey];
var firstValueInMatchingArray = matchingArray[0];
The name of a variable is just something for you, the developer, to use to know which thing is which. It's just a handle for a place in memory where stuff is stored. As such, it doesn't mean anything to the code. If you actually want to use it in the program, then it is data, not code, and should be encoded in a data structure like a dictionary as above. That way you can pass the array or the identifier around as much as you please, and the behaviour of the code doesn't have to be tied to the names you give your variables.
Edit 1:
The newly added code, in dictionary form/object notation:
ActiveDocument.gaShapeArrays = {
'gaShapesTab1' : [
ActiveDocument.Sections["Dashboard"].Shapes["Shape1"],
ActiveDocument.Secti‌​ons["Dashboard"].Shapes["Shape2"]
],
'gaShapesTab2' : [
ActiveDocument.Sections["Dashboard"].Shapes["Shape3"],
ActiveDocument.Secti‌​ons["Dashboard"].Shapes["Shape4"]
],
'gaShapesTab3' : [
ActiveDocument.Sections["Dashboard"].Shapes["Shape5"],
ActiveDocument.Secti‌​ons["Dashboard"].Shapes["Shape6"]
]
}
So each key (e.g. 'gaShapesTab1') is paired with an array value ([...]). This is instead of using new Array() everywhere.
Once you have found the key of the array containing a reference matching your object, you'll have that key as a string (e.g. "gaShapesTab3"). You can't change this string in-place, and I don't think you'd want to. If you could clarify why you need to change the name of the array, perhaps it will be clear how to resolve the problem. For example, do you have other code that needs the array to have a particular name?
Array's name? Arrays do not have names. You only have variable names, variables that store your arrays. If you have a two-dimensional array, you need to grab the "coordinates".
So:
if(object == gaShapeArrays[x][y])
{
// Found the object! It's in [x][y], so in array gaShapeArrays[x] which
// itself is in gaShapeArrays
}
Even though I think #Phil H gave me the answer to my question, as the proper way to do it, I have other reasons to do it the way #ben336 was commenting. It might not be proper, but I'm posting what the solution was in the end. Fortunately, I already had the gaSidetabs array elsewhere in my startup script for another function. I just assigned a string value to the .name property of each array. Would've been nice to know if there was a way to "get at" the symbolic name (or whatever you want to call it) that I called the array, but it sounds like that's just not possible.
ActiveDocument.gaShapesTab1 = new Array(ActiveDocument.Sections["Dashboard"].Shapes["Shape1"],ActiveDocument.Sections["Dashboard"].Shapes["Shape2"]);
ActiveDocument.gaShapesTab2 = new Array(ActiveDocument.Sections["Dashboard"].Shapes["Shape3"],ActiveDocument.Sections["Dashboard"].Shapes["Shape4"]);
ActiveDocument.gaShapesTab3 = new Array(ActiveDocument.Sections["Dashboard"].Shapes["Shape5"],ActiveDocument.Sections["Dashboard"].Shapes["Shape6"]);
ActiveDocument.gaShapeArrays = new Array(gaShapesTab1, gaShapesTab2, gaShapesTab3);
ActiveDocument.gaSidetabs = new Array('Tab1','Tab2','Tab3');
// Assigns a .name javascript property to each array. assumes the order and length of the arrays is the same.
if (gaShapeArrays.length == gaSidetabs.length)
{
for (var x = 0; x < gaShapeArrays.length; x++)
{
gaShapeArrays[x].name = gaSidetabs[x];
}
}
else
{
Console.Writeln('Warning: gaShapeArrays and gaSidetabs are not the same length. Some names will not be assigned.');
}
// go through an array of arrays
for(var x=0; x<gaShapeArrays.length; x++)
{
// and go through the objects of each one
for(var y=0; y<gaShapeArrays[x].length; y++)
{
// if "object" is in the array
if(object == gaShapeArrays[x][y])
{
// get "sidetab" from object's array's name
var sidetab = gaShapeArrays[x].name.replace('gaShapes',''); // assumes that shapearrays will have naming convention gaShapesSidetab
// we found it, we can stop now
break;
}
}
}
Alert(sidetab);
Also glad I could figure out how to retain the format of the code block, here.

Javascript use reserved keyword as key

Doing so
var x = new Array();
x['length']=5;
will make x an array of 5 undefined items, but I actually want to have the value '5' stored at key 'length'.
Is that possible?
In javascript arrays do not have keys. You are looking for objects:
var x = {}
x.length = 5;
I have to parse a file containing many words and store the number of occurences of each word
Use an object, and make the words the keys. You aren't storing sequential / ordered data, so you shouldn't use an array.
var word_count = {};
for (var i; i < words.length; i++) {
var word = words[i];
if (word_count[word]) {
word_count[word]++;
} else {
word_count[word] = 1;
}
If you want to do this you'd be better off creating an object rather than an array. This should give you what you want.
var x = {};
x['length'] = 5;
You can call methods on a javascript object using two different syntaxes. The familiar 'dot' syntax with parens to invoke the method, and the square bracket syntax. You can 'call' a method on a javascript object using the syntax myObj["methodname"](args). This is handy when you want to construct the method name dynamically using strings. Remember, objects in javascript are very much like a hash table (dictionary) where keys denote property and function names. If a key's value holds a function, it can be invoked (using parentheses).
In your example, Array has a method called 'length'. You are inadvertently calling its setter (which sets the length of the array to empty values, i.e., undefined).
Putting that all aside, you really do want a hash (associative array) in this case. An array is an offset indexed data structure.
A simple object literal like myObj = {} will suffice to give you hash semantics (again, objects in javascript are already like hashes) and you can then call myObj.whatever = "some value"
You could use objects instead of arrays to store your data. But if you need to use Arrays (you might need to use their functionality), You could cripple the words and store them as array keys.
Use some kind of simple rule to follow to bypass all the possible keywords. For example prefix all your array keys with a "_" character. This way you could always restore the original words from the keys, by simply removing their first character, and you are sure you are not referencing any specific property of the Array objects (like the length property).

How do I create a dynamic key to be added to a JavaScript object variable [duplicate]

This question already has answers here:
Add a property to a JavaScript object using a variable as the name? [duplicate]
(14 answers)
Closed 8 years ago.
I'm trying something like this, but this example does not work.
jsObj = {};
for (var i = 1; i <= 10; i++) {
jsObj{'key' + i} = 'example ' + 1;
}
What can I do to make a dynamic key like this?
Square brackets:
jsObj['key' + i] = 'example' + 1;
In JavaScript, all arrays are objects, but not all objects are arrays. The primary difference (and one that's pretty hard to mimic with straight JavaScript and plain objects) is that array instances maintain the length property so that it reflects one plus the numeric value of the property whose name is numeric and whose value, when converted to a number, is the largest of all such properties. That sounds really weird, but it just means that given an array instance, the properties with names like "0", "5", "207", and so on, are all treated specially in that their existence determines the value of length. And, on top of that, the value of length can be set to remove such properties. Setting the length of an array to 0 effectively removes all properties whose names look like whole numbers.
OK, so that's what makes an array special. All of that, however, has nothing at all to do with how the JavaScript [ ] operator works. That operator is an object property access mechanism which works on any object. It's important to note in that regard that numeric array property names are not special as far as simple property access goes. They're just strings that happen to look like numbers, but JavaScript object property names can be any sort of string you like.
Thus, the way the [ ] operator works in a for loop iterating through an array:
for (var i = 0; i < myArray.length; ++i) {
var value = myArray[i]; // property access
// ...
}
is really no different from the way [ ] works when accessing a property whose name is some computed string:
var value = jsObj["key" + i];
The [ ] operator there is doing precisely the same thing in both instances. The fact that in one case the object involved happens to be an array is unimportant, in other words.
When setting property values using [ ], the story is the same except for the special behavior around maintaining the length property. If you set a property with a numeric key on an array instance:
myArray[200] = 5;
then (assuming that "200" is the biggest numeric property name) the length property will be updated to 201 as a side-effect of the property assignment. If the same thing is done to a plain object, however:
myObj[200] = 5;
there's no such side-effect. The property called "200" of both the array and the object will be set to the value 5 in otherwise the exact same way.
One might think that because that length behavior is kind-of handy, you might as well make all objects instances of the Array constructor instead of plain objects. There's nothing directly wrong about that (though it can be confusing, especially for people familiar with some other languages, for some properties to be included in the length but not others). However, if you're working with JSON serialization (a fairly common thing), understand that array instances are serialized to JSON in a way that only involves the numerically-named properties. Other properties added to the array will never appear in the serialized JSON form. So for example:
var obj = [];
obj[0] = "hello world";
obj["something"] = 5000;
var objJSON = JSON.stringify(obj);
the value of "objJSON" will be a string containing just ["hello world"]; the "something" property will be lost.
ES2015:
If you're able to use ES6 JavaScript features, you can use Computed Property Names to handle this very easily:
var key = 'DYNAMIC_KEY',
obj = {
[key]: 'ES6!'
};
console.log(obj);
// > { 'DYNAMIC_KEY': 'ES6!' }
Associative Arrays in JavaScript don't really work the same as they do in other languages. for each statements are complicated (because they enumerate inherited prototype properties). You could declare properties on an object/associative array as Pointy mentioned, but really for this sort of thing you should use an array with the push method:
jsArr = [];
for (var i = 1; i <= 10; i++) {
jsArr.push('example ' + 1);
}
Just don't forget that indexed arrays are zero-based so the first element will be jsArr[0], not jsArr[1].

Categories