Creating an associative array using JavaScript - javascript

I am trying to create an associative array in JavaScript:
<script>
var cst_dta = new Array('name' => 'amar', 'total_bill' => 'akbar', 'phone' => 'anthony');
$(document).ready(function(){
alert(cst_data);
});
</script>
But the above code is not alerting anything! What's wrong with the array?

Didn't it occur to you that JavaScript isn't PHP?
This is simply not the correct syntax.
Use:
var cst_dta = {
'name' : 'amar',
'total_bill' : 'akbar',
'phone' : 'anthony'
};
You have much more details on object literals (and other literals) on this page.

You can use objects as associative arrays:
var cst_dta = {name:'amar',total_bill:'akbar',phone:'anthony'};
And you can access it as,
cst_data['name'] or cst_data['phone'] or ..
But it doesn’t seem very useful in this case. Here cst_data.name is fine to use.
Basically, objects are used as associative arrays to bind arbitrary strings to arbitrary values, usually dynamically. Like for example, here you are getting a stock name value from the user at runtime:
var stock_name = get_stock_name_from_user();
var shares = get_number_of_shares();
portfolio[stock_name] = shares;
Since the user enters stock names at runtime, there is no way that you can know the property names ahead of time. Since you can't know the property names when you write the program, there is no way you can use the . operator to access the properties of the portfolio object.
You can use the [] operator, however, because it uses a string value (which is dynamic and can change at runtime) rather than an identifier (which is static and must be hardcoded in the program) to name the property.

Related

How can I use variables in an update operation in mongodb that involves an array or another type of embedded or nested document?

The document in the target collection ("myCollection") has a field called "japanese2". This is an array (or an object) that contains an object that contains a property called "japanese2a". The value of this property is initially set to 0 (although it may change later). I want to change this value to 100 with a script in node.js (I am using the Express framework). The database is Mongodb, the free cloud version called Atlas.
If I do this without using variables, it works well:
db
.collection("myCollection")
.updateOne({username:username}, {"$set":{"japanese2.0.japanese2a":100}});
However, if I try this using variables for both the field name, "japanese2", and the name of the element/property in the array/object, "japanese2a", it fails. I have tried the below and other variations but I couldn't find a solution. I have researched stackoverflow for an answer but couldn't find a solution.
There is only one element/property in the array/object to start with.
var field = req.body.fieldName; //want to set this for the field name="japanese2"
var task = req.body.question; //want to set this for the name of the element="japanese2a"
var myField = [task];
field = myField;
var fieldPos = field[0];
.
.
.
db
.collection("myCollection")
.updateOne({username:username}, {"$set":{[fieldPos]:100}});
The above creates a new field called "japanese2a":100" but it does not appear in the array under the field called "japanese2", which is what I want.
I don't get any error messages when I do the above in the console (probably mostly due to the fact that I haven't put in error statements/functions to catch errors), but the output is not correct.
Another way of updating that I found from here:
https://www.codementor.io/#prasadsaya/working-with-arrays-in-mongodb-16s303gkd3
that involves using something like this:
db.posts.updateOne(
{ _id : ObjectId("5ec55af811ac5e2e2aafb2b9"), "comments.user": "Database Rebel" },
{ $set: { "comments.$.text": NEW_CONTENT } }
)
doesn't work for me, as I don't know if the initial value of the element in the array will always be a zero or some other constant. And there is only one element in the array initially. I can only use the username for the match part in the updating. I can't make an expression that is a perfect match for some element in the array.
The update solution from here: MongoDB update data in nested field
db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.0.email" : '2222'} });
works, and that is what I used successfully to update in the first updating attempt above, but I don't know how to incorporate variables into the updating operation, specifically a variable for the field name ("japanese2") that holds the array or the object, and the name of the first and only element/property in the array/object ("japanese2a").
EDITED: I asked for a solution for an "array" originally, but either a field that acts an array (that holds elements that act as objects) or an object (that holds other objects as properties) works in my case, so I edited the question body and title. Also, the accepted solution works with the field as an entity that holds an array, or as an entity that contains an object inside it.
In either case, if there is already a field with the appropriate name, an object is created (if it didn't already exist) as an object of that object called "field" or the array called "field", and the object's property is set as according to the variables in the script.
If the field doesn't exist, it's created (as an object), and this object contains another object that contains the property ("task" as the name and "100" as the value for the name-value pair). So the newly created "field" object contains an object as its property. The property of this object is a name-value pair of "japanese2a" and "100".
If the script is run again, with a different "task" name (eg. "japanese2b"), another property is created, with the name of "japanese2b" and the value of "100". It is created within that same object that is "inside" the "field" object, so the object field.0 (the object within the "field" object) ends up looking like this: {japanese2a: 100, japanese2b: 100}. And the object called "field" looks like this: {{japanese2a: 100, japanese2b: 100}}.
I think something like
var field = req.body.fieldName // japanese2
var task = req.body.question; // japanese2a
var updateObj = { $set : {} };
updateObj.$set[field + '.0.' + task] = 100
db
.collection("myCollection")
.updateOne({username:username}, updateObj);
Might work

javascript array indexing with large integers

I have a strange problem. I need a multidimensional javascript array that has numeric indexes e.g.:
MyArray = new Array();
$(".list-ui-wrapper").each(function(){
var unique = $(this).attr('id').replace(/[^\d.]/g,'');
MyArray ["'"+unique+"'"] = new Array();
});
The unique is a 8 digit integer. So if I dont wrap it inside the quotes, the ListUI_col_orders array will become extremly big, because if the unique = 85481726 then javascript will fill the array with 85481725 undefined elements before the the new empty array at the 85481726th index.
My problem is that later if i generate the unique again i cannot access the array anymore:
var unique = $(this).attr('id').replace(/[^\d.]/g,'');
console.log(MyArray [unique]); // undefined
console.log(MyArray ['"'+unique+'"']); // undefined
console.log(MyArray [unique.toString()]); // undefined
Any tips?
If you are going to use an array that's mostly sparse, then use a Hash table instead.
eg, set your variable as follows:
ListUI_col_Orders = {};
Then your indexing will be a key, so you don't have to worry about all the interstitial elements taking up space.
...because if the unique = 85481726 then javascript will fill the array with 85481725 undefined elements before the the new empty array at the 85481726th index.
No, it won't. JavaScript standard arrays are sparse. Setting an element at index 85481725 results in an array with one entry, and a length value of 85481726. That's all it does. More: A myth of arrays
The problem is that you're trying to retrieve the information with a different key than the key you used to store it. When storing, you're using a key with single quotes in it (actually in the key), on this line of code:
MyArray ["'"+unique+"'"] = new Array();
Say unique is 85481726. That line then is equivalent to this:
MyArray ["'85481726'"] = new Array();
Note that the key you're using (the text between the double quotes) has ' at the beginning and end. The actual property name has those quotes in it. Since it doesn't fit the definition of an array index, it doesn't affect length. It's a non-index object property. (How can you add a property to an array that isn't an array index? Arrays are not really arrays, see the link above.)
Later, you never use that key when trying to retrieve the value:
var unique = $(this).attr('id').replace(/[^\d.]/g,'');
console.log(MyArray [unique]); // undefined
console.log(MyArray ['"'+unique+'"']); // undefined
console.log(MyArray [unique.toString()]); // undefined
The keys you tried there were 85481726, "85481726" (with double quotes), and 85481726 again. Note that you never tried '85481726' (with single quotes), which is the key you used originally. Since you didn't use the same key, you didn't get the value.
Either use consistent quotes, or (much better) don't use quotes at all. Don't worry about the array length being a large number, JavaScript arrays are inherently sparse. Adding an entry with a large index does not create several thousand undefined entries in front of it.
All of that being said, unless you need the "array-ness" of arrays, you can just use an object instead. Arrays are useful if you use their features; if you're not using their array features, just use an object.
More about the sparseness of arrays: Consider this code:
var a = [];
a[9] = "testing";
console.log(a.length); // 10
Although the length property is 10, the array has only one entry in it, at index 9. This is not just sophistry, it's the actual, technical truth. You can tell using in or hasOwnProperty:
console.log(a.hasOwnProperty(3)); // false
console.log("3" in a); // false
When you try to retrieve an array element that doesn't exist, the result of that retrieval is undefined. But that doesn't mean there's an element there; there isn't. Just that trying to retrieve an element that doesn't exist returns undefined. You get the same thing if you try to retrieve any other property the object doesn't have:
var a = [];
a[9] = "testing";
console.log(a[0]); // undefined
console.log(a[200]); // undefined
console.log(a["foo"]); // undefined
Final note: All of this is true of the standard arrays created with [] or new Array(). In the next spec, JavaScript is gaining true arrays, created with constructors like Int32Array and such. Those are real arrays. (Many engines already have them.)

Javascript multidimensional arrays with alphanumeric keys

This seems to be a common source of confusion from what I've seen, and apparently I'm no exception. I've read a few tutorials on this, and I still can't quite get my head around it. From what I can gather, Arrays are objects in Javascript, just like Strings and other variable types. But I still don't get how that helps me declare a multidimensional array with alphanumeric keys.
In PHP I can simply write:
$calendar = array();
foreach ($schedule->currentExhibitions as $key) {
$calendar[$key["ExhibitionID"]]["startDate"] = date("Y,n,j", strtotime($exhibition["StartDate"]));
$calendar[$key["ExhibitionID"]]["endDate"] = date("Y,n,j", strtotime($exhibition["StartDate"]));
}
But in Javascript trying something similar will create errors. Should I create an Array and fill it will Objects? If so, how would I go about doing so? Or should I just use an Object entirely and skip having any sort of Array? (If so, how do I create a multidimensional Object?)
Sorry for the newbish quesion!
If your keys are strictly numerical and ordered starting at zero, then an array makes sense and you can use square bracket notation just like you would in php, although you will need to initialize sub-arrays if you want to have multiple dimensions :
var myArray = [];
myArray[0] = [];
myArray[0][0] = "something interesting";
If your keys are not numerical, ordered and starting at zero, then you should use an object (all keys are strings), which still allows the square bracket notation :
var myObject = {};
myObject["1A"] = {};
myObject["1A"]["3B"] = "something interesting";
In Javascript, an array is an object, who's keys are numerical, sequential, indexes.
As soon as you want to use alpha-numerica (aka strings) keys, you use a regular object.
In JS to do what you want, you'd do the following (using more or less your php code).
var calendar = {};
Object.keys(schedule.currentExhibitions).forEach(function(key) {
var ex = schedule.currentExhibitions[key];
calendar[ex.exhibitionId] = calendar[ex.exhibitionId] || {}; //if the key doesn't exist, create it.
calendar[ex.exhibitionId].startDate = date(); //some js date function here
calendar[ex.exhibitionId].endDate = date(); //your js date function here
});
I look at Multidimension as nesting, and at multiple levels of nestings as complex objects. For example:
var parent = [];//top holder
var child1 = {};
child1.name = "Jim";
parent.push(child1);
In this simple example, you can access child1 like this:
parent[0]["name"] //Jim
So that is, in a way, multidemensional. Instead of using ["name"] as an indexer, or child1 as an object it could also be an array, like this:
var parent = [];//top holder
var child1 = [];
child1.push("Jim");
parent.push(child1);
In this example, you could get Jim with:
parent[0][0];//Jim
So for complex examples you may have multiple levels of these nestings (or dimensions).
parent[0]["Child"].grandChild[5]["cousin"].name //etc
Where that would just be a continuation of the previous examples down the line.
If you want to preserve order or you want to access by numeric index, use an array. The value of the array can be a single value or an object or array itself (so each value in the array can contain more than a simple value).
If you want to access by a unique alphanumeric key, then use an object and assign properties to it.
Arrays have numeric indexes. They do not have alphanumeric indexes.
Objects have string keys.
Because an array is also an object, it can have both types of keys, but using a string key is not an array access, it's accessing a property of the object.
When you ask for the .length of an array, you only get the length of the numeric indexes. It does not include other properties of the object.
An array of objects is a very practical data structure in javascript and is used quite often when either order or index by numeric index is important.
If order is not important or you don't need to access by numeric index and just want to access by an alpha numeric string, then you should just use an object and set a properties on it with keys that are your alphanumeric string.

Can an Object object be coerced into an Array object?

Crockford writes in http://javascript.crockford.com/survey.html:
"There are two ways to make a new array:
var myArray = [];
var myArray = new Array();"
So I'm confused by these two lines in some AJAX code I am reading:
var obj={}; // obj is an Object object (i.e. a hash table)
obj[4] = 'x'; // now obj is suddenly an Array object via an integer key?
In JavaScript are an object and an array really just the same thing, but with a variant on the key type?
In other words, is this the same as in php where we can use either a name (string) or an integer for a hash key?
I've Googled for an answer on this but can't seem to nail down an article which discusses this issue.
One possibility that comes to mind is that perhaps the first line is syntactic lint because the 2nd line overwrites the previous definition of obj as it creates a new Array object.
it does not become an array, it is simply an Object with a '4' property, like this:
var obj = {
'4': 'x'
};
it is just converted to a string when used as a property like obj['4'] = 'x';
Everything but primitive datatypes is an object in JavaScript. Objects can have a properties and there are two ways to access object properties:
Dot notation, foo.bar, which you can use as long as the property name is a valid identifier.
Bracket notation, foo['bar'] which you have to use if the key is not a valid identifier [spec]. For example, if it is a number, or contains a space or you have a variable with the name.
Hence, bracket notation is not a characteristic of arrays and if you see it, it does not mean the value is an array. It is simple one of two ways of accessing properties.
The elements of an array are just properties with numeric keys. Arrays are built on top of objects and implement some additional methods which treat these numeric properties in a special way. For example the .length property is automatically updated when you add new elements. But ultimately they are just normal properties.
In your example you have a simple object. You have to access the property with obj[4] or obj['4'] because obj.4 is invalid since 4 is not a valid identifier (basically everything that you can use as variable name is a valid identifier. var 4 = 'foo'; is invalid).
And since arrays are just objects, if you could use numbers as identifiers, you were also able to access an element with arr.4.
As far as I know, no, an object can't be coerced into an array. But, it can look and act like an array, and that's what's happening here. Numbers, and anything else that can be coerced to a string, are perfectly valid property names for Javascript objects, so
obj[4] = 1;
obj['spam'] = 2;
are both valid ways of setting a property on the object. That doesn't make the object an array. An Array is a special class of object with specific methods (.slice(), .concat(), etc) and a length property that's kept up to date with the number of items in the array.
Yes
Javascript Array is very different from tradition array, you can think of it as object.
var array = [1,2,3] is equivalent to var object = {'0' : 1, '1' : 2, '2' : 3}
except array inherited from Array.prototype and object inherited from Object.prototype, where Array.prototype will contain method such as length.
Javascript is a loosely-typed, prototype-based language. Even primitive types like a boolean can be treated like an object (though you aren't going to get far). Almost everything in javascript is, at root, an object.
Understanding this, an array IS an object. You can arbitrarily add properties to any object:
var xml = new XMLHttpRequest();
xml[4] = 'x';
console.log(xml);
That object is still an instance of XMLHttpRequest. It now has a property labeled 4 with a value of x. You can treat anything like this -- even a function:
var test_func = function () {
alert('woah!');
}
test_func[4] = 'x';
console.log(test_func[4]);
The take-away here is that the obj[key] = value notation is NOT indicative of an "array" type, like it is in languages such as PHP. Rather, it is an alternate way to access properties of any object, and is equivalent to obj.key = value (you can't use obj.4 = 'x', though, that's invalid syntax). The other take-away is that any object in javascript can be modified or used in pretty much any way. You shouldn't misuse objects, but you can
Check it out here: http://jsfiddle.net/w2AqJ/
Documentation
Array on MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array
Javascript "associative arrays" considered harmful by Andrew Dupont - http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/

How can I prevent extra array elements being created in Javascript?

In PHP, if you do this
$var = array();
$var[5000] = 1;
echo count($var);
It prints 1.
In JS it makes the "missing" elements.
<script type="text/javascript">
var fred = [];
fred[10] = 1;
alert(fred.length);
</script>
Alerts "11".
Can I prevent this? Is it good for anything? I'm a PHP coder trying to adapt to Javascript.
EDIT:
I'm working on an app that uses Google Maps v2 and markerManager. The code has been working for ages, but a problem has suddenly arisen in Chrome (17.0.963.56 m) where markers seem to be duplicated (or more) and then rendering moved markers goes completely wrong, often followed by a browser freeze-up. Looking in the DOM using Firebug, I found gazillions of "undefined" elements in arrays under the grid_ variable in markerManager. I figured that, if I could remove these, I might have slicker code, whether it fixes the marker problem or not. Thanks.
As a PHP coder, you're accustomed to array keys being fairly arbitrary. In JavaScript however, if you assign an array element numerically that doesn't exist, the array will be allocated with empty elements up to the one you created. That's the behavior you found. Objects, on the other hand, denoted by {} rather than [], accept arbitrary property names (with caution) and function a little more closely to how you're accustomed PHP's array structures functioning. This is not to say that JavaScript objects (or object literals) are a direct analogue to PHP arrays....
If what you want is a data structure with a key called "10", that is a job for an object literal (though it isn't great practice to name object properties numerically.
var fred = {};
fred["10"] = 1;
Note, the more normal syntax of dealing with an object literal is the object.property notation, but that is not valid for numeric properties:
// name as a property
fred.name = "fred";
// Syntax error...
fred.10 = 10;
// Use [] notation for numeric properties:
fred["10"] = 10;
Object literals do not have a length property, however. So you cannot do:
fred.length;
// undefined
You may use an object instead of an array, but you loose some of the benefits of an array, like access to a length property.
<script type="text/javascript">
var fred = {};
fred['10'] = 1;
// alert(fred.length); // won't work anymore
</script>
On the other hand no extra entries will be generated and the access to a specific value works almost the same way as in an array. If you want to traverse all values, use the following:
for( var el in fred ) {
if ( fred.hasOwnProperty( el ) ) {
alert( fred[ el ] );
}
}

Categories