Why can my js code set values to undefined array indexes? - javascript

As I know an Array element in JavaScript can itself be another Array, hence creating layers of arrays within one another. I am tring to define an array like:
[Array(821), Array(821), Array(821), Array(821)]
As You see, this is an array with 4 elements each of which will contain an array of 821 elements.
Now, I also know Arrays can be dynamically resized using Array.push("new value") method, otherwise an undefined error will be thrown. Therefore, I defined each and every one of the array elements as being an array itself:
var htmlOBJs = {};
htmlOBJs.tabular = [];
for (var i = 0; i < 5; i++){
htmlOBJs.tabular.push([]);
}
Now, when I want to access an element inside the inner array htmlOBJs.tabular[2][100], surprisingly no undefined error is thrown. Why? Am I not supposed to push indexes up the inner array up to 100?

The reason the undefined error isnt thrown is as you push to the tubular array this causes a new entry created. This means now it is a multidimensional array. To cause the undefined error to throw you would have to go 3 levels deep.
There is an interesting reason for empty arrays which has been described way better but basically the first parameter for the Array constructor is a size and not actually filling this array:
to do this you can use the fill method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill - you may need to map over this after to make sure these are unique values.

Related

What is the correct way to access nested objects in JSON?

If I understand correctly, list in this code is an array that consists of objects. I want to access temp in the main object and thought main.temp would do the trick, but I get an error message stating it’s undefined. Alternatively I’ve tried list[1].main.temp. What is the correct way to access nested arrays like this?
What is the correct way to access nested arrays like this?
First of all these aren't nested arrays, but array of objects instead and in an array we access the items by index, and in objects we access them(entries) by keys.
So in your case list[0] is an object where list[0].dt is an entry and list[0].main is another entry of the object, so dt isn't at index 0 like you mentioned in your comment.
And to access all your array main.temp properties you need to loop throught the array elements using one of the Array built-in methods or just a for loop, because using static indexes in list[1].main.temp will just get the temp property of the firts element in the array and may throw an exception if this index is higner than the array.length.
This is how should be your code:
for(var i=0; i<list.length; i++){
console.log(list[i].main.temp);
}

Length of the javascript array does not change after deleting the element from it

I am trying to copy one array values into another, but without breaking the links that is associated with this array other words i can not just assign the new array to this value, thats why i cannot use methods like slice() or concat().
Here is the code of the function that does the thing:
self.updateBreadcrumbs = function (newBreadcrumbs) {
var old_length = self.breadcrumbs.length;
var new_length =newBreadcrumbs.length;
var j = new_length > old_length ? new_length: old_length;
for (var i = 0; i < j; i++) {
if(old_length < i+1){
self.breadcrumbs.push(newBreadcrumbs[i]);
continue;
}
if(new_length < i+1){
delete self.breadcrumbs[i];
continue;
}
if (self.breadcrumbs[i].title !== newBreadcrumbs[i].title) {
self.breadcrumbs[i] = newBreadcrumbs[i];
}
}
}
My problem is that length of the array does not change when i delete something from the array.
P.S If you know any easier way to do this i am totally open for propositions.
Length of an Array can never change by deleting elements in it.
However It can be altered with splice
eg.
var arr=[1,2,3,4,5]; //length 5
arr.splice(0,1); //length 4
Unlike what common belief suggests, the delete operator has nothing to do with directly freeing memory. delete is only effective on an object's properties. It has no effect on array length
The splice() method changes the content of an array by removing
existing elements and/or adding new elements.
More about Splice
The length property of an Array object is a property that is maintained by it's methods, it is not an inherent characteristic of the object itself. So, if you take an action on it that is not one of Array's own methods, it will not update the length property. In this case, it is the splice method that you would want to use ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice )
Interestingly, you can change the makeup of an array by directly altering its length . . . for example, if you have an array with 6 elements in it and you were to change its length property to 5 (i.e., array.length = 5;), it would no longer recognize the 6th element as being part of the array.
More on the length property: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length
An Array is (aside from its prototype methods) not much more than a simple object. The difference is in the length property which has a spcieal setter method, and the different way of adding a new property.
If a property is added to the object, its name is tested for being a numerical value and whether this value is >= the current array length. if so, the internal length is updated.
If the length is set, it is checked, whether the new value is smaller than the old one, and if so, all own properties with a property name that is a numerical value and >= the new length will be deleted.
If you delete an indexed element from an array, it will just be deleted (and accessing this index later will return undefined, as it would do with any non-existent property). It won't change the array length, nor will increasing the array length create any properties for the added index positions (sparse array). Using [] or new Aray[10000] will both create Arrays with exactly the same memory footprint. Just the length property has a different initial value.
This is completely different from Arrays in other languages, where an array of size n will have n storage spaces reserved for the elements (being pointers to objects or being native value types). So in other languages, creating an array with a given size and filling it is faster than creating an empty array and adding values (in which case each time a larger consecutive space must be allocated and the array must be copied to this larger memory psoition before adding the element). OTOH, accessing the elements of an JS array is somewhat slower (as they are just named properties which have to be located in the property list first) than in other languages where an element is at its given, fixed position.
This answer will not help if you use array, but.
If you still need to delete item by key and you can use object:
$o = {'blue' : '', 'apple' : '', 'red' : ''};
console.log(Object.keys($o).length); // will output 3
delete $o['apple'];
console.log(Object.keys($o).length); // will output 2

put content of all elements of class into array..why do i get these error messages

I'm trying to load text of all divs that have a particular class into an array, but this
var temp = $('.theClass').text();
temp = temp.toArray();
console.log(temp);
keeps giving me the error
Uncaught TypeError: Object has no method 'toArray'
And
var tempArr = [];
var temp = $('.theClass').text();
for (var t in temp){
tempArr.push(t);
}
console.log(tempArr);
results in an array filled with many, many objects within objects just filled with integers.
An explanation of how to do this properly can be found here, but I wonder if someone could provide me with an explanation for why I get these errors. Thanks!
You can use map to iterate over each element of the matched set and return some data (in this case, the text). You can then use get to convert the resulting jQuery object into an actual array:
var arr = $('.theClass').map(function () {
return $(this).text();
}).get();
Your first attempt fails because the text method returns a string, and strings don't have a toArray method (hence your "Object has no method" error).
Your second attempt fails because you're iterating over the string with the for...in loop. This loop iterates over the characters of the string. Each iteration t is assigned the index of the character, so you end up with an array, with one element for each character in the string. You should never really be using a for...in loop for iterating over anything other than object properties, and even then, you should always include a hasOwnProperty check.

Creating multi-dimensional arrays in javascript, error in custom function

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'";

Iterating over two arrays at a time in Javascript

I want to iterate over two arrays at the same time, as the values for any given index i in array A corresponds to the value in array B.
I am currently using this code, and getting undefined when I call alert(queryPredicates[i]) or alert(queryObjects[i]).
I know my array is populated as I print out the array prior to calling this.
//queryPredicates[] and queryObjects[] are defined above as global vars - not in a particular function, and I have checked that they contain the correct information.
function getObjectCount(){
var variables = queryPredicates.length; //the number of variables is found by the length of the arrays - they should both be of the same length
var queryString="count="+variables;
for(var i=1; i<=variables;i++){
alert(queryPredicates[i]);
alert(queryObjects[i]);
}
The value of the length property of any array, is the actual number of elements (more exactly, the greatest existing index plus one).
If you try to access this index, it will be always undefined because it is outside of the bounds of the array (this happens in the last iteration of your loop, because the i<=variables condition).
In JavaScript the indexes are handled from 0 to length - 1.
Aside of that make sure that your two arrays have the same number of elements.
If queryPredicates does not have numerical indexes, like 0, 1, 2, etc.. then trying to alert the value queryPredicates[0] when the first item has an index of queryPredicates['some_index'] won't alert anything.
Try using a for loop instead:
stuff['my_index'] = "some_value";
for (var i in stuff)
{
// will alert "my_index"
alert(i);
// will alert "some_value"
alert(stuff[i]);
}
Arrays in JS are zero based. Length is the actual count. Your loop is going outside the bounds of the array.

Categories