JavaScript array's length method - javascript

Can anyone explain why the second alert says 0 ?
var pollData = new Array();
pollData['pollType'] = 2;
alert(pollData['pollType']); // This prints 2
alert(pollData.length); // This prints 0 ??

The length of the array is only changed when you add numeric indexes. For example,
pollData["randomString"] = 23;
has no effect on length, but
var pollData = [];
pollData["45"] = "Hello";
pollData.length; // 46
changes the length to 46. Note that it doesn't matter if the key was a number or a string, as long as it is a numeric integer.
Besides, you are not supposed to use arrays in this manner. Consider it more of a side effect, since arrays are objects too, and in JavaScript any object can hold arbitrary keys as strings.

Because you haven't put anything into the array yet. You've only been assigning to a dynamically-created pollType attribute on the array object.
If you use numeric indices, then the array automagically takes care of length. For example:
var arr = [ ]; // same as new Array()
arr[2] = 'Banana!';
alert(arr.length); // prints 3 (indexes 0 through 2 were created)

The length property takes into consideration only those members of the array which names are indexes (like '1', '2', '3', ... ).

Arrays in JavaScript have numeric indexes only.
Use an object, which is essentially what you are doing above, setting properties on that array object.

array.length returns how many values are stored in the array. The first alert is returning the value of the position 'pollType'.
The reference guide I always use when needing help with javascript arrays is this page http://www.hunlock.com/blogs/Mastering_Javascript_Arrays
I'd also read what it says under the heading Javascript Does Not Support Associative Arrays, as you may run into problems with this also.

var pollData = Array();
function test() {
pollData[0] = 2
alert(pollData[0]);
alert(pollData.length);
}
//[x] is the array position; hence ['polltype'] is causing issues

Related

How to initialize array length and values simultaneously in new Array()?

Let’s consider, I have to initialize an Array with some values
So I can achieve this by writing following code.
var arr = new Array("a", "b", "c", "d")
console.log(arr)
Similarly, I have to determine the length of the array before using it.
So I can achieve this by following code.
var arr = new Array(5)
console.log(arr.length)
Finally, I have a following questions ?
Is it possible to initialize an array with array length and different values (not similar values) simultaneously using new Array() ?
How to initialize a single integer value using new Array() ?
EDIT:
here, different values refers there are some specific string values.
I know it is straightforward when using array literals. but that's not exactly what I want.
The answer for both questions is no. Looking at the docs, there are two overloads for the Array function.
A JavaScript array is initialized with the given elements, except in the case where a single argument is passed to the Array constructor and that argument is a number (see the arrayLength parameter below).
If the only argument passed to the Array constructor is an integer between 0 and 232-1 (inclusive), this returns a new JavaScript array with its length property set to that number.
Only these two possibilities exist, there is no overload for specifying both the size and the values of an array.
You can create and fill an array like so:
let a = Array(100).fill(null)
console.log(a)
Or to increment your filled values:
let i=0,a = Array(100).fill(0).flatMap(x=>[x+i++])
console.log(a)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
You could use .fill().
console.log(new Array(5).fill(2));
// [2, 2, 2, 2, 2]
Is it possible to initialize an array with array length and values simultaneously using new Array() ?
As far as I know, this isn't possible yet.
How to initialize a single integer value using new Array() ?
That would be k => new Array(1).fill(k). But if I had to choose, I'd use k => [k]. Note it is recommended not to use new Array() in other scenarios than to initialize it's lenght. But even then, you should rather be sure you are giving it an integer because the behaviour of new Array(n) is a bit erratic, and won't throw you an error when you wish it did.
Actually, I wish it was not possible to initialize an array with value using new Array(). The worst being using new Array(...args), whose behaviour will change dramatically when args is [5]. You should stick to [] arrays if you want to initialize an array with values.
Array("") gives [""]
Similarly Array([]) gives [[]] and Array({}), [{}]
Array(5) gives an array with 5 empty slots
Array(2.5) produces an Uncaught RangeError: Invalid array length.
Also, Array() gives []
Note: This is Chromium's behaviour. I didn't check Firefox.
There are few ways to create an array:
1) Literals
const a = [1,2,3];
console.log(a);
But you say you don't want to use it.
2) Array constructor:
const a = new Array(10); //array of length 10
console.log(a);
const b = new Array(1,2,3);
console.log(b); // array with elements 1,2,3
But you say that you don't want to go for it
3) Array.from
const a = Array.from(new Array(10), (val, ind) => ind); // array of 10 values and map applied to these elements
console.log(a);
Over these 3 ways, you have the Array.fill method, which can be called with static values only:
const a = new Array(10);
console.log(a.fill(5)); // array of 10 number elements with value of 5
Considering your case, maybe your solution could be to go with Array.from, using the map function you can provide as second parameter.
You could think to create some function like the following:
function createMyArray(length, start, end) {
return Array.from(new Array(length), (val, ind) => ind >= start && ind <= end ? ind : undefined);
}
console.log(createMyArray(5, 2, 4));
console.log(createMyArray(5, 1, 3));
console.log(createMyArray(10, 2, 6));
The question you should ask to yourself is: Where and how is the data I want to use coming from? Otherwise this is really too much vague
Is it possible to initialize an array with array length and different values (not similar values) simultaneously using new Array() ?
No you cannot do that with the Array constructor only.
An alternative way is to do it like this:
var a = ['a', 'b', 'c', 'd'];
a.length = 10;
console.log(a);
How to initialize a single integer value using new Array() ?
You can't. This is what happens when you try to do so according to the specification:
Array(len)
[...]
Let intLen be ToUint32(len).
If intLen ≠ len, throw a RangeError exception.
Let setStatus be Set(array, "length", intLen, true).
Assert: setStatus is not an abrupt completion.
Return array.
Use the other ways to create an array instead (e.g. [1] or Array.of(1)).
Here's a different but related take on initializing an array without using an array literal.
let arr = [...Array(10)].map((emptyItem, index) => index);
// [0,1,2,3,4,5,6,7,8,9]
I can't find documentation that matches how this expression is constructed, so I can't fully explain it. But it is using the spread syntax to spread 10 empty items into an array.

Why can't you access this array with index?

Why does this array have a length property of 0? And as a follow up to that question, why can't you access an item in this array with an index value?
Consider the following:
var box = [];
box['material'] = 'cardboard';
box['size'] = 'small';
box.length; //0
console.log(box);
//[ material: 'cardboard', size: 'small' ]
box[0]; //undefined
However, when I do the following:
var box = [];
box['0'] = true;
box['1'] = 'cardboard';
box['2'] = 'some value';
box.length; //3
box[0];// true
Why does it output the correct length in this case, since '0' is a string and not a number and access the correct item with the 0 index?
In JavaScript, the length of an array is always one more than the largest numeric (integer) property name. Arrays can have properties whose names are not numeric, but they don't count towards the length of the array (and they are ignored in some other important situations).
Object property names are always strings, but strings that are non-negative integer values when interpreted as numbers are special in arrays. Accessing properties with numeric values works because the numbers are first converted to strings; thus box[0] and box['0'] do exactly the same thing.
when setting box['material'] it creates a property called 'material' with value 'cardboard'. this doesn't add a element to the list!
you need to use .push() or asign the index you want.
also, the '0' string is cased to a number, so obj['0'] and obj[0] is the same (not just for 0, this happens for all numbers)
I think you’re confusing objects with arrays. While arrays are indeed objects in javascript, that doesn’t help us here.
What you are trying to instantiate is an associative array with key-value pairs “material”->“cardboard”, “size”->“small”. However, such a datastructure does not exist in javascript. Array must only have integers as indexes, as in
box = [];
box[0] = 'material';
box[1] = 'someValue';
The reason why your code (which only seems to be an associative array)
box = [];
box['0'] = true;
box['1'] = 'cardboard';
works is because of implicit type conversion. Because you’ve declared box to be an array, a string is not valid in this position, so javascript quietly converts it into an integer, so you again get a plain, boring, integer-indexed array as above.
What you can do, though, is create an object with attributes. So you might, for example, state
box = {}; // box is now an object
box.size = 'small'; // box now has an attribute called “size”
// which has the (string) value “'small'”
box.material = 'cardboard';
or at one go using the notation for object literals:
box = {
size: 'small',
material: 'cardboard'
};
This is the closest you can get to associative arrays in javascript. Note that objects do not have a length. If you want to access the number of attributes they have, you have to use Object.keys(box).length. To iterate over the keys, use
for(var key in box){
console.log('value of ' + key + ' is ' + box[key])
}
Note the array-like notation here, but remember: You’re dealing with objects, not arrays, though dealing with them looks similar. Since box is of type object, you will not only get the attributes you have defined yourself, but also any attributes which are defined for every object. To get only the keys you put in there yourself, use
for (var key in box) {
if (box.hasOwnProperty(key)) {
// do stuff
}
}
If you need to add keys, i.e. attributes at runtime, use (for example)
//supposing that box was instantiated as above
var listOfBoxAttributes = ['shape', 'color', 'weight'];
for(var i in listOfBoxAttributes)
box[listOfBoxAttributes[i]] = undefined;

Javascript Array with number as property name

var myArray = new Array();
myArray['112'] = 0;
myArray.length
Why is length 113 in above sample? Shouldn't '112' add a object property for the array and create something similar to myArray = {"112":0}?
Besides this, why is the length 113 and not 1? Since myArray actually only contains 1 value
The array length is one more than the highest index, so you get 113.
No. The '112' string and a pure numeric 112 evaluate to the same thing when JS is doing the array lookup, so you get a slot in the array rather than a property.
Simplest to think of a JS Array indexes as properties that happen to be numbers, even in string form. It's more chameleonic than you'd think at first.
But if you add a property with some nonnumeric name, like myArray['foo'], it will do as you expect and the length won't change.
Consider this simple example:
var aa = [];
aa[3] = 'three';
alert( aa.length // 4
+ '\n' + aa[2] // undefined
+ '\n' + aa.hasOwnProperty('2') // false
);
The number 3 is used to assign the property name, but it is converted to a string and used as a standard property name (i.e. the string "3").
Adding a property named "3" has created one property and set the length to 4 since the length is always set to one more than the largest non-negative integer property name.
No other property is created, the array is "sparse", i.e. it doesn't have sequentially named (numbered) members. A for..in loop can also be used to see that there is only one property.
You got array of 0..112 elements - in total length of 113 elements.

Javascript (beginner): Performance issue using arbitrary numerical properties?

When I do something like this:
var o = new Array();
o[20] = true;
o[1000] = true;
o[4000] = true;
Is it reasonable to expect that only 3 elements will be allocated or can the implementation decide to suddenly allocate something with 4000 elements?
The reason I'm asking is that when I do this I see in firebug an indication that there are actually 4000 undefined in o. are they really there?
Now that we know that o is an Array, I can answer you precisely.
No, the elements will not be 'allocated' or 'created'.
When you make an assignment of an index property to an Array object, which is greater than the actual length of the array two things happen:
The index named property is created
The length property is incremented, to be the index + 1
For example:
var o = [];
o[4000] = true;
o.hasOwnProperty(0); // false, the property doesn't exist
o.hasOwnProperty(1); // false
o.hasOwnProperty(4000); // true, the property exist
As you can see, the hasOwnProperty method returns false when we test the presence of the 0 or 1 properties, because they don't exist physically on the object, whereas it returns true for 4000, the property that was created.
When Firebug detects that the object being printed in the console is an array-like object, it will simply make a loop, showing each of the index values from 0 to length - 1.
Firebug detects array-like objects simply by looking if they have a length property whose its value is an unsigned 32-bit integer (less than 2^32 - 1), and if they have a splice property that is a function, for example, the following object will be detected and printed as an Array on the Firebug's console:
console.log({length:3, splice:function(){}});
// Firebug will log: `[undefined, undefined, undefined]`
a) That code is not valid. You need either var o = {}; // object or var o = []; // array.
b) In the first case, the object is sparse. In the second, it may depend on the interpreter; in modern browsers it is also sparse. Try o[99999999] = "hi"; and see how much memory your browser does or does not allocate. If it does not go up by at least 10MB, your arrays are sparse.
I think this one answers the question.
Are Javascript arrays sparse?
And according to that one, arrays are spares, thats is, if you use for(item in array) you only get 3 items, not 4000 but if you use array.length it will take the larges integer value and return one larger, look here:
http://www.crockford.com/javascript/survey.html
Linkpad will use a for(item = 0; item < array.length; item++) and that one will return undefined for any index that is not present in the array.
/*
On the other hand, if you have a very large index any array manipulation will have to loop
through each index- it won't skip from one defined item to the the next defined item.
*/
var A= [];
A[0]= 'a';
A[10]= 'b';
A[4000000]= 'c';
alert(A.filter(function(itm){
return itm!= undefined;
}));
Javascript will generate all elements inbetween, always. You may want to use o.length to verify the length of the array. It will return 4000 and not 3.

Question about the for loop in javascript?

In the following code why the variable 'a' refer to the index rather than the value ?
for (var a in Values) {
alert(Values[a]);
}
That's by design. It's trivial to get a value in an array when you know its key, but it's much harder to get a key given a value. Values can be duplicated, so how do you know which key should be used? But a key's unique, so given a key, there's only ever one value to retrieve. So, the for loop will iterate over the keys, and it's trivial to get the associated value.
Think of a JavaScript Array as a normal Object with a special property named length (actually, it a bit more complex). So the for..in loop behaviour is identical as for other objects:
var a = new Array();
a[1] = "a";
alert(a.length); // 2
alert(a[0]); // undefined
a[1000] = "b"
alert(a.length); // 1001
a[-1] = "c";
alert(a[-1]); // c
a.abc="why not";
for(var key in a)
{
alert(key+"="+a[key]);
}
// 1=a
// 1000=b
// -1=c
// abc=why not
Also note that you can have gaps within your array without having to pay the memory price.
There is a for each...in loop that does exactly that - enumerates only values. Coming soon to a browser near you.
for each(var a in Values) {
..
}
For arrays, there is a new function forEach which achieves the same.
someArray.forEach(function(value) {
..
});

Categories

Resources