Why can't I do array[-1] in JavaScript?
Question:
In Python, you can do that:
arr = [1,2,3]
arr[-1] // evaluates to 3
But in JS, you can’t:
let arr = [1,2,3];
arr[-1]; // evaluates to undefined
The question is: why?
I know about the tricks to get around it (arr[arr.length-1]
, modifying the array prototype, etc), but that is not the point.
I’m trying to understand why it is still not in the EcmaScript standards to interpret negative array indices as indices starting from the end, despite that it seems pretty easy to implement a JS engine that understands that (and also, the whole Python community is having a blast with this notation).
What am I missing?
Answers:
You miss the point, that arrays are objects (exotic object) and -1
is a valid key.
var array = [1, 2, 3];
array[-1] = 42;
console.log(array);
console.log(array[-1]);
You can use arr[-1]
– it will try to access the -1
property on the arr
object, which is possible when weird code has assigned to the negative index. For example:
const arr = [1,2,3]
arr[-1] = 'foo';
console.log(arr[-1]);
Javascript property access has always worked this way – so, changing things so that [-1]
will refer to the last item in the array would be a breaking change, which the standards strive very hard to avoid. (remember how they backed out of the Array.prototype.flatten
name due to incompatibility with an extremely old and obsolete version of MooTools which still exists on only a few sites – this would be far worse)
Because most languages like the indexOf
function to return -1
instead of a needless exception. If -1
is a valid index then following code would result in 3
instead of undefined
.
var arr = [1,2,3]
console.log(arr[arr.indexOf(4)])
IMHO, Python made a mistake by make negative indexes valid, because it leads to many strange consequences that are not directly intuitive.
As others said, In Javascript array[-1]
is just a reference to a property of array
named "-1"
(like length
) that is usually undefined
(because array['-1']
is not evaluated to any value). But there are other ways:
UPDATE (2021):
.at()
method is now available in a wide range of environments:
- Chrome / Edge / Chrome Android / WebView Android: v92+
- Firefox / Firefox for Android: v90+
- Opera: v78+
- Node: v16.6.0 (V8 9.2) +
- Deno: v1.12+
- More info …
Check if your browser supports it or not:
const array = [1, 2, 3]
try {
console.log(array.at(-1)) // 3
console.log(array.at(-2)) // 2
console.log(array.at(-3)) // 1
console.log(array.at(-4)) // undefined
} catch (e) {
console.error("Sorry! Your browser doesn't support this feature yet!nSee:nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at#browser_compatibility")
}
The at()
method takes an integer value and returns the item at that index, allowing for positive and negative integers. Negative integers count back from the last item in the array.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at
Use .slice(-N)[0]
:
const array = [1, 2, 3]
console.log(array.slice(-1)[0]) // 3
console.log(array.slice(-2)[0]) // 2
console.log(array.slice(-3)[0]) // 1
In String
s you have another option (instead of [0]
).
const string = 'ABC'
console.log(string.slice(-1)) // 'C'
console.log(string.slice(-2, -1)) // 'B'
console.log(string.slice(-3, -2)) // 'A'
Or using .substr(-N, 1)
:
const string = 'ABC'
console.log(string.substr(-1)) // 'C'
console.log(string.substr(-2, 1)) // 'B'
console.log(string.substr(-3, 1)) // 'A'
In Python, you can do that:
arr = [1,2,3]
arr[-1] // evaluates to 3
But in JS, you can’t:
let arr = [1,2,3];
arr[-1]; // evaluates to undefined
The question is: why?
I know about the tricks to get around it (arr[arr.length-1]
, modifying the array prototype, etc), but that is not the point.
I’m trying to understand why it is still not in the EcmaScript standards to interpret negative array indices as indices starting from the end, despite that it seems pretty easy to implement a JS engine that understands that (and also, the whole Python community is having a blast with this notation).
What am I missing?
You miss the point, that arrays are objects (exotic object) and -1
is a valid key.
var array = [1, 2, 3];
array[-1] = 42;
console.log(array);
console.log(array[-1]);
You can use arr[-1]
– it will try to access the -1
property on the arr
object, which is possible when weird code has assigned to the negative index. For example:
const arr = [1,2,3]
arr[-1] = 'foo';
console.log(arr[-1]);
Javascript property access has always worked this way – so, changing things so that [-1]
will refer to the last item in the array would be a breaking change, which the standards strive very hard to avoid. (remember how they backed out of the Array.prototype.flatten
name due to incompatibility with an extremely old and obsolete version of MooTools which still exists on only a few sites – this would be far worse)
Because most languages like the indexOf
function to return -1
instead of a needless exception. If -1
is a valid index then following code would result in 3
instead of undefined
.
var arr = [1,2,3]
console.log(arr[arr.indexOf(4)])
IMHO, Python made a mistake by make negative indexes valid, because it leads to many strange consequences that are not directly intuitive.
As others said, In Javascript array[-1]
is just a reference to a property of array
named "-1"
(like length
) that is usually undefined
(because array['-1']
is not evaluated to any value). But there are other ways:
UPDATE (2021):
.at()
method is now available in a wide range of environments:
- Chrome / Edge / Chrome Android / WebView Android: v92+
- Firefox / Firefox for Android: v90+
- Opera: v78+
- Node: v16.6.0 (V8 9.2) +
- Deno: v1.12+
- More info …
Check if your browser supports it or not:
const array = [1, 2, 3]
try {
console.log(array.at(-1)) // 3
console.log(array.at(-2)) // 2
console.log(array.at(-3)) // 1
console.log(array.at(-4)) // undefined
} catch (e) {
console.error("Sorry! Your browser doesn't support this feature yet!nSee:nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at#browser_compatibility")
}
The
at()
method takes an integer value and returns the item at that index, allowing for positive and negative integers. Negative integers count back from the last item in the array.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at
Use .slice(-N)[0]
:
const array = [1, 2, 3]
console.log(array.slice(-1)[0]) // 3
console.log(array.slice(-2)[0]) // 2
console.log(array.slice(-3)[0]) // 1
In String
s you have another option (instead of [0]
).
const string = 'ABC'
console.log(string.slice(-1)) // 'C'
console.log(string.slice(-2, -1)) // 'B'
console.log(string.slice(-3, -2)) // 'A'
Or using .substr(-N, 1)
:
const string = 'ABC'
console.log(string.substr(-1)) // 'C'
console.log(string.substr(-2, 1)) // 'B'
console.log(string.substr(-3, 1)) // 'A'