Destructuring to get the last element of an array in es6
Solution 1
It is not possible in ES6/2015. The standard just doesn't provide for it.
As you can see in the spec, the FormalParameterList
can either be:
- a
FunctionRestParameter
- a
FormalsList
(a list of parametes) - a
FormalsList
, followed by aFunctionRestParameter
Having FunctionRestParameter
followed by parameters is not provided.
Solution 2
console.log('last', [1, 3, 4, 5].slice(-1));
console.log('second_to_last', [1, 3, 4, 5].slice(-2));
Solution 3
I believe ES6 could at least help with that:
[...arr].pop()
Given your array (arr) is not undefined and an iterable element (yes, even strings work!!), it should return the last element..even for the empty array and it doesn't alter it either. It creates an intermediate array though..but that should not cost much.
Your example would then look like this:
console.log( [...['a', 'b', 'program']].pop() );
Solution 4
You can destructure the reversed array to get close to what you want.
const [a, ...rest] = ['a', 'b', 'program'].reverse();
document.body.innerHTML =
"<pre>"
+ "a: " + JSON.stringify(a) + "\n\n"
+ "rest: " + JSON.stringify(rest.reverse())
+ "</pre>";
Solution 5
another approach is:
const arr = [1, 2, 3, 4, 5]
const { length, [length - 1]: last } = arr; //should be 5
console.log(last)
George Simms
Updated on February 12, 2022Comments
-
George Simms over 2 years
In coffeescript this is straightforward:
coffee> a = ['a', 'b', 'program'] [ 'a', 'b', 'program' ] coffee> [_..., b] = a [ 'a', 'b', 'program' ] coffee> b 'program'
Does es6 allow for something similar?
> const [, b] = [1, 2, 3] 'use strict' > b // it got the second element, not the last one! 2 > const [...butLast, last] = [1, 2, 3] SyntaxError: repl: Unexpected token (1:17) > 1 | const [...butLast, last] = [1, 2, 3] | ^ at Parser.pp.raise (C:\Users\user\AppData\Roaming\npm\node_modules\babel\node_modules\babel-core\node_modules\babylon\lib\parser\location.js:24:13)
Of course I can do it the es5 way -
const a = b[b.length - 1]
But maybe this is a bit prone to off by one errors. Can the splat only be the last thing in the destructuring?
-
caub almost 8 yearsuhh, it's quite bad, even
.slice(-1)[0]
is slighly less bad, orvar [last]=arr.slice().reverse()
is another ugly one if you need -
shoesel almost 8 yearsI thought this post was about ES6/ES2015, no? But I like especially your last piece. How about combining the two:
var [last] = arr.slice(-1)
;) -
caub almost 8 yearsmy favorite way is
Object.defineProperty(Array.prototype, -1, { get() {return this[this.length - 1] } }); [1,2,3][-1]
-
shoesel over 7 yearsI love javascript :)
-
Vadorequest over 7 yearsSmart. Better than
const last = ['bbb', 'uuu', 'iii'].slice(-1);
? In terms of performances? -
shaunc over 7 years
a = [1, 2, 3, 4, 5]; eval(`[${('' + a).replace(/[^,]/g, '')}x] = a`); x
yields5
:) -
shoesel almost 7 years@shaunc: This only works for simple types, try adding an object to the array.
-
Jack Steam almost 7 yearsNice simple non-mutative solution.
-
Bergi over 6 yearsI don't see any elegance in this solution, but anyway @shoesel already posted it
-
GavKilbride over 6 yearsAlthough this works it's mutative and removes the item from the original array. Not ideal in many scenarios.
-
Dave Newton almost 6 years@Shanimal Depends, I'm getting the
pop
version as faster (OS X, Chrome 68). -
Dan almost 6 years@GavKilbride it doesn't. Example is the same as
[].concat(arr).pop();
which doesn't mutatearr
. -
Antonio Pantano almost 6 years@Dave Newton But pop() cause mutation
-
Dave Newton almost 6 years@AntonioPantano Yes, it mutates the copy. Point was whether or not it's faster isn't a given.
-
mix3d over 5 yearsthe
.slice(-1)
is technically faster, but it does not give you both the last item AND the subarray in one call, which is a benefit of the...
splat when destructuring. Performance hit of reversing twice is to be considered when used on longer arrays, but for a small script probably worth the convenience? But you could just as easilylet a = array.slice(-1), rest = array.slice(0,array.length-2)
if you still wanted the oneliner in ES5, that is ~4% faster. jsperf.com/last-array-splat -
andrhamm over 4 yearsYes, I find it useful when already doing other destructuring. By itself it is not as easy to read as the classic solution.
-
Hashbrown over 4 years@caub for your first comment, instead of the reverse, I'd probably do
let [last] = arr.slice(-1);
instead of reverse if you're going to use slice and destructuring anyway -
petitkriket over 3 yearsshould be the selected solution
-
oriadam over 3 yearsto return the value
'program'
and not['program']
use['a','b','program'].slice(-1)[0]
. for empty array this will returnundefined
-
Константин Ван about 3 yearsYou don’t have to catch the
length
....rest
would be more useful. -
Shane Hsu about 3 yearsI must add that JavaScript Array reverse is done in-place. So this solution might not suit every person, and/or have performance issues. I've been burned...
-
Den Kerny about 3 years@КонстантинВан true, it's common, mine is rare, but trully useful
-
ncubica about 2 yearsthis is quite clever :D
-
Mg Gm about 2 yearsThis solution still mutates the original array , which is not ideal in real life scenarios.
-
VLAZ about 2 yearsBasically the same as this solution. It still has the same problem of mutating the array.
-
VLAZ about 2 yearsThere is no advantage at all to use
reverse()
. It takes unnecessary time and it mutates the array which is most likely also unnecessary. With mutation.pop()
should be the idiomatic way to get the last item. Without mutation it'sarr[arr.length - 1]