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).
Related
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].
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.
I was trying to define an array (including other arrays as values) in a single javascript statement, that I can loop through to validate a form on submission.
The function I wrote to (try to) create inline arrays follows:
function arr(){
var inc;
var tempa = new Array(Math.round(arguments.length/2));
for(inc=0; inc<arguments.length; inc=inc+2) {
tempa[arguments[inc]]=arguments[inc+1];
}
return tempa;
}
This is called three times here to assign an array:
window.validArr = arr(
'f-county',arr('maxlen',10, 'minlen',1),
'f-postcode',arr('maxlen',8, 'minlen',6)
);
However in the javascript debugger the variable is empty, and the arr() function is not returning anything. Does anyone know why my expectations on what this code should do are incorrect?
(I have worked out how to create the array without this function, but I'm curious why this code doesn't work (I thought I understood javascript better than this).)
Well from what your code does, you're not really making arrays. In JavaScript, the thing that makes arrays special is the management of the numerically indexed properties. Otherwise they're just objects, so they can have other properties too, but if you're not using arrays as arrays you might as well just use objects:
function arr(){
var inc;
var tempa = {};
for(inc=0; inc<arguments.length; inc=inc+2) {
tempa[arguments[inc]]=arguments[inc+1];
}
return tempa;
}
What you're seeing from the debugger is the result of it attempting to show you your array as a real array should be shown: that is, its numerically indexed properties. If you call your "arr()" function as is and then look at (from your example) the "f-county" property of the result, you'll see something there.
Also, if you do find yourself wanting a real array, there's absolutely no point in initializing them to a particular size. Just create a new array with []:
var tempa = [];
Your code works. Just inspect your variable, and you will see that the array has the custom keys on it. If not expanded, your debugger shows you just the (numerical) indixed values in short syntax - none for you.
But, you may need to understand the difference between Arrays and Objects. An Object is just key-value-pairs (you could call it a "map"), and its prototype. An Array is a special type of object. It has special prototype methods, a length functionality and a different approach: to store index-value-pairs (even though indexes are still keys). So, you shouldn't use an Array as an associative array.
Therefore, their literal syntax differs:
var array = ["indexed with key 0", "indexed with key 1", ...];
var object = {"custom":"keyed as 'custom'", "another":"string", ...};
// but you still can add keys to array objects:
array.custom = "keyed as 'custom'";
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].
If I have a Javascript list which will have only numeric keys, which takes less memory?
var array = [];
array[0] = 'hello';
array[5] = 'world';
array[50] = 'foobar';
var obj = {};
obj[0] = 'hello';
obj[5] = 'world';
obj[50] = 'foobar';
I don't know a ton about Javascript engine internals, so...
The reason I ask is because that array, when converted to a string, will have a bunch of undefined's in the middle of it. Are those actually stored in some fashion, or is that just put in at string conversion?
An array is basically an ordered set of values associated with a single variable name.
In your example I think you try to do an associative array, and you should use object, Array is not meant to be used for key/value pairs.
Also the array length is indirecly increased when you assign a value to an index with higher length of the current array length:
var array = new Array();
array[99] = "Test";
// array.length is now 100
Check this detailed article on the subject.
Probably the Javascript array because you can 'only' use numeric key values, where as the object literals provide a space for key values, and even if you use numerical key values, they are probably handled differently than the numerical key values for arrays.
Most likely the reason arrays can't have text-based key values are because they are treated differently than object literals. I'm guessing that because they are probably treated differently, the processing for the array probably is more optimized for numeric key values, were as a object literal is optimized to use strings or numbers as their keys.
JavaScript doesn't implement arrays like other languages so you don't get any performance enhancements inherent of a normal array (memory-wise); in JavaScript an array is very similar to an object; actually, it is essentially an object just with a few extra methods and capabilities (such as a length that updates itself). I'd say neither is quicker.