Reputation: 12181
I hope people will forgive me a fairly basic JavaScript question (it's not generally a "primary" language for me). I was looking at W3Schools's JavaScript tutorial for review; their lesson on arrays has the following warning and code sample:
Warning: Adding elements with high indexes can create undefined "holes" in an array:
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits[6] = "Lemon"; // adds a new element (Lemon) to fruits
This will result in indices 4 and 5 containing undefined
.
Furthermore, I can do something like alert(fruits[20]);
(which gives me a popup saying "undefined") without exception.
In most languages that are more strict about typing, trying to do either of those actions would result in a runtime exception. I do realize that none of us on here were on the JavaScript design committee (as far as I know), but does anyone know why are these allowed (i.e. why don't they throw runtime exceptions or something like that)?
I can understand the purpose of doing something like fruits[4] = "Lemon"
(because that's essentially appending to the array), but is there ever a valid reason to do something like fruits[6] = "Lemon"
?
It also seems like doing something like alert(fruits[20]);
would almost always indicate a bug - I can't think of any legitimate use case for it actually. Is this correct?
My understanding from the answers to this question is that JavaScript arrays "are actually more like custom objects that use the properties as indexes" than they are like arrays in Java or C#. One of the answers also states
Javascript arrays are not true arrays like in C/C++ or other languages. Therefore, they aren't as efficient, but they are arguably easier to use and do not throw out of bounds exceptions.
Are these statements correct? Is this the reason for this behavior in JavaScript?
Upvotes: 2
Views: 1940
Reputation: 19354
In answer to your question, first a demonstration:
var a = [];
console.log( "initial length is: " + a.length);
a[1.5] = 1.5
console.log( "a[1.5] is " + a[1.5] + ", length is " + a.length);
a["foo"] = "bar";
console.log( "a.foo is " + a.foo + ", length is " + a.length);
a[-1] = -1;
console.log( "a[-1] is " + a[-1] + ", length is " + a.length);
a[10] = "item 10";
console.log( "a[10] is " + a[10] + ", length is " + a.length);
a[20] = "item 20";
console.log( 'a[ 20 ] is ' + a[ 20 ] + ", length is " + a.length);
console.log( 'a["20"] is ' + a["20"] + ", length is " + a.length);
console.log( 'a["0x14"] is ' + a["0x14"]);
console.log( "a.hasOwnProperty( 20) " + a.hasOwnProperty( 20));
console.log( "a[ 15] " + a[ 15]);
console.log( "a.hasOwnProperty( 15) " + a.hasOwnProperty( 15));
a[15] = undefined;
console.log( "a[ 15] " + a[ 15]);
console.log( "a.hasOwnProperty( 15) " + a.hasOwnProperty( 15));
Array
constructor and inherit methods from Array.prototype
.a[20]
as a["20"]
. You can't reference the same element as a["0x14"]
because the property string name "0x14" does not exist.undefined
values for missing elements. undefined
is returned when trying to lookup an element which is not there. (This is the same behavior as when looking up object properties which don't exist.)undefined
is a primitive value, you can set an array element to undefined
. The element now exists rather than not being found.Upvotes: 3
Reputation: 58
I see that you have said that it's not your primary language... so i will compare with c++
In c++ you declare a portion of memory: int a[50];
// the System rezerved for us a portion of 50 * sizeof(int) where we can do a what we want. a is a pointer to the first int
for example: cout<<a[20]
; // will return the variable on the memory that is there, its our portion of memory, even if we didn't set it early.
cout<<a[51]
// error... why?... because the program will try to access an adress that we don't have acces( or OS didn't granted );
in js you can do: console.dir(fruits); ... you will see a lot of functions there,... even the "length" property you didn't say in fruits to set a length property right?... basic in js the array is a class in c++
In c++ when you refer to an array, you refer to the memory of pointer A + the size of type of array:
Example : cout<<*A
; // same as cout<<A[0];
or cout<<*(A+0);
cout<<*(A+5)
; // same as cout<<A[5];
A[5] = *(A+5) = *(5+A) = 5[A]
so
for(int i=0; i<n; i++)
cout<<i[A];
// same as cout<<A[i]
.. crazy huh?
Upvotes: 2
Reputation: 30330
In C or another language with "true" arrays (i.e. a sequence of pointers in contiguous memory), an out-of-bounds write could corrupt the running program or even another process.
JavaScript's Array
can dynamically resize, so there is no risk of illegal access or corruption.
As a rule JavaScript only throws runtime exceptions when there is no alternative. In this case there is an alternative - to dynamically resize the array - so it prefers that to throwing.
Upvotes: 5
Reputation: 781848
Javascript doesn't treat accessing nonexistent array elements and object properties as errors. It simply returns undefined
when the code attempts those accesses.
Some common idioms take advantage of this. You can write:
var fruit20 = fruits[20] || defaultFruit;
Since undefined
is falsey, it will return defaultFruit
when it doesn't exist. This is simpler than:
var fruit20 = '20' in fruits ? fruits[20] : defaultFruit;
Often you'll get an error from the code that tries to use the resulting value. For instance, if you do:
var firstLetter = fruits[20].substr(0, 1);
it will signal an exception due to trying to access the substr
property of undefined
, because undefined
doesn't have any properties.
Upvotes: 2