Why does JavaScript not throw an exception for this code sample?

耗尽温柔 提交于 2019-12-24 08:46:56

问题


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?


回答1:


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.




回答2:


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.




回答3:


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?




回答4:


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));
  • Arrays in JavaScript are considered exotic objects. They behave as ordinary objects except when setting properties with non-negative integral numeric values.
  • Arrays are constructed by the global Array constructor and inherit methods from Array.prototype.
  • The length property is maintained as one more than the highest, non negative integral property contained in the array (this is the exotic part).
  • Both the index and value of an element are stored in the array. Numeric indices are converted to a radix 10 formatted string value used as the (object) property name of the element. While unusual in code, you could reference a[20] as a["20"]. You can't reference the same element as a["0x14"] because the property string name "0x14" does not exist.
  • The technical name for and array with "holes" in it is "sparse array".
  • Sparse arrays do not contain 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.)
  • Because undefined is a primitive value, you can set an array element to undefined. The element now exists rather than not being found.
  • One explanation of why JavaScript arrays are called "associative" is that they do not reserve memory for array content which has not been set. It is likely they have to search a list of property names when accessing an element with valid numeric index, without saying what kind of search that might be.


来源:https://stackoverflow.com/questions/42495568/why-does-javascript-not-throw-an-exception-for-this-code-sample

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!