How are floating point array indices interpreted?

2020-08-09 09:06发布

问题:

I can't find any information on this, but suppose I have

var arr = [1, 2, 3];
var x = arr[1.5];

I assumed that Javascript would floor the index and returns the item at index 1, but it seems at least in Chrome it just returns undefined.

Is this correct? I can't find any standard or documentation that confirms this. It's actually really inconvenient if so because I assumed the round-down behavior allows you to pass any float in the range [0, n) to an array index, but it seems you'll silently break your arrays if you do floating point math which isn't rounded.

Edit: if anyone's maintaining a list of javascript gotchas, please add this one. Now I have to review 10k lines of javascript code to see where this assumption I made is quietly causing bugs!

回答1:

According to MDN: Array, array items are actually properties, and properties are identified by strings.

Accessing arr[1.5] is therefore the same as accessing arr['1.5'], and Firefox does actually do it that way.

This code:

var x = [0,1,2,3,4,5];

x[1.5] = 42;

alert(x);
alert(x['1.5']);
alert(x['1.50']);

outputs:

 0, 1, 2, 3, 4, 5
 42
 undefined

So, the item accessed using a floating point value is a property identified by the string representation of the number. Note that accessing an item using '1.50' is not the same as accessing an item using '1.5', so the index is not converted to a number.

I tested this in Internet Explorer and Chrome also, and they both do the same as Firefox.



回答2:

I don't know why you think Chrome would "round" or "floor" the value when accessing an Array, but it doesn't do that at all. Neither does Firefox. It's just accessing a "key" which is not there and both browsers correctly return the undefined value (at least in the latest versions which I'm testing on).
Since Arrays are also Objects in ECMAscript, you're just accessing the value behind the keyname 1.5.

I really think I should point that out a little more. An Array is just an Object (it also inherits from Object) with a .length property and a few added methods. There is no numerical array-access like in C/C++. Its just accessing a keyname of an object.

var foo = [1,2,3];

foo instanceof Array; // true;
foo instanceof Object; // true;


回答3:

That's expected, since js converts the index into a string and accesses the object property (since object property indexes are always strings), so it'll actually look up arr['1.5']

For those non-believers, the relevant part of the standard is 15.4 which clearly defines array index as a string.



回答4:

var arr = [];
arr[0] = "hello";
alert(arr["0"]);
Output : hello

In JavaScript, whenever indexing an array element the index is converted by the JavaScript interpreter into a string which it then uses as a key. This is the same as using a key-value pair Hash Map in java.

arr[5-"5"]

In this case the mathematical expression is evaluated first and the result is converted to a string and used as the key. This is how it works:

<1> The interpreter converts "5" into an integer since "-" operator cannot be used with strings and then subtracts it from the left operand 5 to get the result 0.

<2> The result is then converted to string and used as the key.