Get the last item in an array
Asked Answered
S

63

2101

Here is my JavaScript code so far:

var linkElement = document.getElementById("BackButton");
var loc_array = document.location.href.split('/');
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-2]))); 
linkElement.appendChild(newT);

Currently it takes the second to last item in the array from the URL. However, I want to do a check for the last item in the array to be "index.html" and if so, grab the third to last item instead.

Searchlight answered 9/7, 2010 at 19:45 Comment(0)
G
2443
if (loc_array[loc_array.length - 1] === 'index.html') {
   // do something
} else {
   // something else
}

In the event that your server serves the same file for "index.html" and "inDEX.htML" you can also use: .toLowerCase().

Though, you might want to consider doing this server-side if possible: it will be cleaner and work for people without JS.


EDIT - ES-2022

Using ES-2022 Array.at(), the above may be written like this:

if (loc_array.at(-1) === 'index.html') {
   // do something
} else {
   // something else
}
Goggin answered 9/7, 2010 at 19:48 Comment(11)
if you just need last item you can you Array.pop()Beefburger
@BadriDerakhshan That would inevitably remove the last element from the array before returning it so this is not an option if you merely want to inspect the last element of the array. You would also have to push it back to restore the array to its former state.Levitan
You have to check whether array is empty. Empty array is legal array.Sinhalese
The solution from @BadriDerakhshan is useful for cases where the array created is temporary. For eg. instead of x = string.split('/'); return x[x.length-1], you could do return x.split('/').pop()Phenazine
Doesn't work on SafariTipster
at() method is not supported by Safari IOS, Chrome IOS, and Samsung Internet caniuse.com/mdn-javascript_builtins_string_atElbertelberta
(node:19430) UnhandledPromiseRejectionWarning: TypeError: allMessages.at is not a functionTurnage
I rolled back the update suggesting to use .at as it was added by an entirely different user and is an entirely different approach than the one written by the original author. Here's a dedicated answer with the .at approach: https://mcmap.net/q/44989/-get-the-last-item-in-an-arrayEquiprobable
DO NOT use Array.pop() because it is doing something else, just use .at(-1)Tigges
OMG - SIR thank you. I've been working on this for days. POP IS A HORRIBLE THING. pop() and typescript DONT mix. lol don't do it. do this. omg thank you sir.Spinet
Unfortunately, at() has a possible undefined in typescriptHershel
A
1625

Not sure if there's a drawback, but this seems quite concise:

arr.slice(-1)[0] 

or

arr.slice(-1).pop()

Both will return undefined if the array is empty.

Agiotage answered 23/8, 2012 at 20:19 Comment(6)
using destructuring is nice too: const [lastItem] = arr.slice(-1)Generalization
@Badrush slice() makes new array with a copy of a single element, and pop modifies only that copy. the original array remains unharmedAgiotage
But you should avoid creating new arrays unless this code is not called often. Otherwise it will put an extra strain on garbage collection, and/or will make browser use more memory.Corduroys
@Corduroys i did a benchmark a long time ago, throughput was around one or two million calls per second on a single 2.4ghz thread. so unless you have solve problems you shouldn't solve in JS anyways, it won't be noticable (iirc slowdown compared to arr[arr.length-1] was 50-100x)Agiotage
this method is very slowCytolysin
@Cytolysin please see my comment. you can call this an exorbitant number of times per second. if you need more, or have the array length readily available, use normal array access for maximum performance arr[arr.length-1]Agiotage
C
425

Use Array.pop:

var lastItem = anArray.pop();

Important : This returns the last element and removes it from the array

Chemmy answered 14/6, 2012 at 14:6 Comment(3)
especially great for something like: filename.split('.').pop()Mckeever
it doesnt only return the last element but removes it !Extraversion
const lastItem = [...anArray].pop() would be a way to avoid the mutationSwing
U
219

A shorter version of what @chaiguy posted:

Array.prototype.last = function() {
    return this[this.length - 1];
}

Reading the -1 index returns undefined already.

EDIT:

These days the preference seems to be using modules and to avoid touching the prototype or using a global namespace.

export function last(array) {
    return array[array.length - 1];
}
Urbane answered 1/10, 2012 at 15:8 Comment(9)
If it's not obvious how this is to be actually used, here's an example: var lastItem = [3,2,1,5].last();. The value of lastItem is 5.Canning
This answer is correct and also pretty clean BUT(!!!) A rule of thumb using Javascript is that Do NOT modify objects you Do NOT own. It's dangerous because of many reasons, such as 1. Other developers working in your team could get confused as this method is not standard 2.with any update in libraries or even using a lower or higher ECMAScript version it could easily get LOST!Batory
For anyone wondering, this breaks Array.forEach(). I still agree that modifying prototypes is not the worst thing out there, but this one is bad.Execrable
Imo there's not such a big problem with modifying Array.prototype, but you should use Object.assign(Array.prototype, 'last', { value: function () { … } });. Otherwise the property will be enumerable.Schooling
@FarzadYousefzadeh Interesting article that tells when and how to modify a JS native prototype.Ronn
@Breakingnotsobad Sure polyfilling is approved but keep in mind that it's only done for standard methods or soon to be standard for that matter. last is no standard in this case.Batory
If you’re going to extend built-in prototypes or polyfill a property (i.e. monkey-patch), please do it correctly: for forward compatibility, check if the property exists first, then make the property non-enumerable so that the own keys of constructed objects aren’t polluted. For methods, use actual methods. My recommendation: follow these examples which demonstrate how to add a method that behaves like other built-in methods, as closely as possible.Cannady
note that the advice is to not modify original prototypes because if everybody did, there'd be conflicts all over the place. However, there really is only one thing that Array.prototype.last() can do: no matter the implementation, it'll return the last element, without removing it (because .pop() already exists for that), so in this case it's almost certainly perfectly fine, even if someone else also implements that same function. They'll overwrite each other and keep doing exactly the same thing.Considerate
@黄雨伞 Actually, using Object.assign() does not seem to work here, whereas regular assignment to the prototype object does.Grenadier
F
204

Two options are:

var last = arr[arr.length - 1]

or

var last = arr.slice(-1)[0]

The former is faster, but the latter looks nicer

http://jsperf.com/slice-vs-length-1-arr

Foliole answered 7/1, 2014 at 21:57 Comment(2)
Thanks for for jsperf link. The second option is a nonsense from performance point of view.Meadowlark
The first option is also very obvious what it does. Second one not so muchGoof
S
150

Performance

Today 2020.05.16 I perform tests of chosen solutions on Chrome v81.0, Safari v13.1 and Firefox v76.0 on MacOs High Sierra v10.13.6

Conclusions

  • arr[arr.length-1] (D) is recommended as fastest cross-browser solution
  • mutable solution arr.pop() (A) and immutable _.last(arr) (L) are fast
  • solutions I, J are slow for long strings
  • solutions H, K (jQuery) are slowest on all browsers

enter image description here

Details

I test two cases for solutions:

  • mutable: A, B, C,

  • immutable: D, E, F, G, H, I, J (my),

  • immutable from external libraries: K, L, M,

for two cases

  • short string - 10 characters - you can run test HERE
  • long string - 1M characters - you can run test HERE

function A(arr) {
  return arr.pop();
}

function B(arr) {  
  return arr.splice(-1,1);
}

function C(arr) {  
  return arr.reverse()[0]
}

function D(arr) {
  return arr[arr.length - 1];
}

function E(arr) {
  return arr.slice(-1)[0] ;
}

function F(arr) {
  let [last] = arr.slice(-1);
  return last;
}

function G(arr) {
  return arr.slice(-1).pop();
}

function H(arr) {
  return [...arr].pop();
}

function I(arr) {  
  return arr.reduceRight(a => a);
}

function J(arr) {  
  return arr.find((e,i,a)=> a.length==i+1);
}

function K(arr) {  
  return $(arr).get(-1);
}

function L(arr) {  
  return _.last(arr);
}

function M(arr) {  
  return _.nth(arr, -1);
}






// ----------
// TEST
// ----------

let loc_array=["domain","a","b","c","d","e","f","g","h","file"];

log = (f)=> console.log(`${f.name}: ${f([...loc_array])}`);

[A,B,C,D,E,F,G,H,I,J,K,L,M].forEach(f=> log(f));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js" integrity="sha256-VeNaFBVDhoX3H+gJ37DpT/nTuZTdjYro9yBruHjVmoQ=" crossorigin="anonymous"></script>

Example results for Chrome for short string

enter image description here

Salpinx answered 16/5, 2020 at 15:50 Comment(3)
What is the numbers mentioned? Is higher better?Surprisal
I could guess the results even without you having to run them, lol. But I don't think that performance matters much in this case.Scratchy
This isn't an answer to the question, which didn't discuss performance. There are many other considerations other than performance for choosing a particular solution.Infallibilism
D
101

Getting the last item in an array is possible via the length property. Since the array count starts at 0, you can pick the last item by referencing the array.length - 1 item

const arr = [1,2,3,4];
const last = arr[arr.length - 1];
console.log(last); // 4

Another option is using the new Array.prototype.at() method which takes an integer value and returns the item at that index. Negative integers count back from the last item in the array so if we want the last item we can just pass in -1

const arr = [1,2,3,4];
const last = arr.at(-1);
console.log(last); // 4

Another option is using the new findLast method. You can see the proposal here (currently in stage 4)

const arr = [1,2,3,4];
const last = arr.findLast(x => true);
console.log(last); // 4

Another option is using the Array.prototype.slice() method which returns a shallow copy of a portion of an array into a new array object.

const arr = [1,2,3,4];
const last = arr.slice(-1)[0];
console.log(last); // 4
Dissolute answered 14/1, 2022 at 20:41 Comment(1)
imo it should be arr.findLast(() => true); since your version would not "find" falsy values like 0 or "", ...Arnelle
C
83

Here's how to get it with no effect on the original ARRAY

a = [1,2,5,6,1,874,98,"abc"];
a.length; //returns 8 elements

If you use pop(), it will modify your array

a.pop();  // will return "abc" AND REMOVES IT from the array 
a.length; // returns 7

But you can use this so it has no effect on the original array:

a.slice(-1).pop(); // will return "abc" won't do modify the array 
                   // because slice creates a new array object 
a.length;          // returns 8; no modification and you've got you last element 
Confirmation answered 3/9, 2014 at 21:25 Comment(2)
you should do slice(-1).pop(), otherwise you copy the entire array (you really only need to copy the last element).Agiotage
No need for that pop() then: just do arr.slice(-1)[0]Noto
A
60

The "cleanest" ES6 way (IMO) would be:

const foo = [1,2,3,4];
const bar = [...foo].pop();

This avoids mutating foo, as .pop() would had, if we didn't used the spread operator.
That said, I like aswell the foo.slice(-1)[0] solution.

Australorp answered 16/6, 2017 at 19:43 Comment(4)
You can also use the array destructuring to make it more ES6 ;) https://mcmap.net/q/44989/-get-the-last-item-in-an-arrayHukill
Note that this solution performs a copy of the entire array.Borden
It's just as unreadable as .slice(-1)[0] but it's slower. Might as well use .sliceTweeter
Copying the whole array just for "clean" syntax seems silly to me. It doesnt even look that niceDy
H
58

Previously you can use x[x.length - 1] Update: Since the most recent updates we can use the below method.

const y = x.at(-1)
Huh answered 28/3, 2021 at 22:43 Comment(2)
Definitely better to just use arr[arr.length - 1] as it is both more readable and nearly an order of magnitude faster on most browsers.Scheel
@Scheel I agree, why make it harder when you can make it easier.Logy
D
57

const [lastItem] = array.slice(-1);

Array.prototype.slice with -1 can be used to create a new Array containing only the last item of the original Array, you can then use Destructuring Assignment to create a variable using the first item of that new Array.

const lotteryNumbers = [12, 16, 4, 33, 41, 22];
const [lastNumber] = lotteryNumbers.slice(-1);

console.log(lotteryNumbers.slice(-1));
// => [22]
console.log(lastNumber);
// => 22
Demetrius answered 29/5, 2019 at 10:5 Comment(4)
The .slice(-1) answer was already given multiple times, starting in 2012, and its implications were discussion in detail (unlike here). Please do not give repetitive answers just to get some upvotes.Gilus
I like this answer the best of all. The other .slice(-1) answers I have seen use [0] rather than destructuring. A comment by @Generalization suggested this kind of destructuring, but it deserves to be an answer rather than a comment, in my opinion. Nice examples and links also.Bernadinebernadotte
Yeah those other answers aren't the same Dan, you're missing the use of destructuring assignment from the Array produced by slice(-1).Demetrius
This also allows you to pick e.g. the last two items in a nice syntax: const [secondLast, last] = lotteryNumbers.slice(-2)Ismaelisman
S
47

You can use relative indexing with Array#at:

const myArray = [1, 2, 3]

console.log(myArray.at(-1))
// => 3
Svend answered 17/5, 2020 at 4:54 Comment(6)
And as of 3/2021 it's still in proposal and not supported by any browserOmarr
This is supported since Firefox 88 (Nightly only) and Safari 14.1 (with jscOptions=--useAtMethod=true). The lastItem proposal will probably be withdrawn.Cannady
now on chrome92 it is supported. chromestatus.com/feature/6123640410079232Fp
Good answer, though it would be better if it were called out that this is a new method that's not fully supported by all modern browsers, and not supported by older browsers.Equiprobable
@M.Justin There’s a link to documentation which has a browser support table — should be enough. I’d prefer the most modern solutions to be highlighted. Most things can be polyfilled or transpiled to older environments automatically. In a rapidly evolving ecosystem, developers should probably reconsider writing code for older environments by hand or assuming that everything is supported everywhere.Cannady
Has good browser support now: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Octan
N
46

I'd rather use array.pop() than indexes.

while(loc_array.pop()!= "index.html"){
}
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length])));

this way you always get the element previous to index.html (providing your array has isolated index.html as one item). Note: You'll lose the last elements from the array, though.

Nunnally answered 24/2, 2012 at 18:39 Comment(0)
C
39
const lastElement = myArray[myArray.length - 1];

This is the best options from performance point of view (~1000 times faster than arr.slice(-1)).

Catalase answered 18/6, 2014 at 12:33 Comment(1)
How does this add anything to the top answer?Gilus
H
34

You can use this pattern...

let [last] = arr.slice(-1);

While it reads rather nicely, keep in mind it creates a new array so it's less efficient than other solutions but it'll almost never be the performance bottleneck of your application.

Hukill answered 29/9, 2017 at 9:13 Comment(0)
A
31

If one wants to get the last element in one go, he/she may use Array#splice():

lastElement = document.location.href.split('/').splice(-1,1);

Here, there is no need to store the split elements in an array, and then get to the last element. If getting last element is the only objective, this should be used.

Note: This changes the original array by removing its last element. Think of splice(-1,1) as a pop() function that pops the last element.

Antares answered 16/3, 2012 at 0:53 Comment(3)
Doesn't this return the last element in an array, instead of the last element itself?Leisaleiser
@tozazaburo isn't that the same thing?Urbane
this modifies the array. you could use slice(-1) instead of splice(-1) to leave the original array untouched. @AramKocharyan no its not, compare ["hi"] vs "hi".Agiotage
B
31

Getting the last item of an array can be achieved by using the slice method with negative values.

You can read more about it here at the bottom.

var fileName = loc_array.slice(-1)[0];
if(fileName.toLowerCase() == "index.html")
{
  //your code...
}

Using pop() will change your array, which is not always a good idea.

Bunnie answered 12/2, 2013 at 9:13 Comment(2)
Slice returns an array, though, so use arr.slice(-1)[0], like this answer.Newman
If performance is an issue, know that this method is a lot slower than array[array.length - 1] jsperf.com/get-last-item-from-array/13Pontifex
P
31

Multiple ways to find last value of an array in javascript

  • Without affecting original array

var arr = [1,2,3,4,5];

console.log(arr.slice(-1)[0])
console.log(arr[arr.length-1])
const [last] = [...arr].reverse();
console.log(last)

let copyArr = [...arr];
console.log(copyArr.reverse()[0]);
  • Modifies original array

var arr = [1,2,3,4,5];

console.log(arr.pop())
arr.push(5)
console.log(...arr.splice(-1));
  • By creating own helper method

let arr = [1, 2, 3, 4, 5];

Object.defineProperty(arr, 'last', 
{ get: function(){
  return this[this.length-1];
 }
})

console.log(arr.last);
Pitzer answered 6/9, 2019 at 13:55 Comment(1)
If your first example where you state "Without affecting original array" and by doing as suggested: console.log(arr.reverse()[0]) - congratulations, you just modified the original array.Grube
F
29

This question has been around a long time, so I'm surprised that no one mentioned just putting the last element back on after a pop().

arr.pop() is exactly as efficient as arr[arr.length-1], and both are the same speed as arr.push().

Therefore, you can get away with:

---EDITED [check that thePop isn't undefined before pushing]---

let thePop = arr.pop()
thePop && arr.push(thePop)

---END EDIT---

Which can be reduced to this (same speed [EDIT: but unsafe!]):

arr.push(thePop = arr.pop())    //Unsafe if arr empty

This is twice as slow as arr[arr.length-1], but you don't have to stuff around with an index. That's worth gold on any day.

Of the solutions I've tried, and in multiples of the Execution Time Unit (ETU) of arr[arr.length-1]:

[Method]..............[ETUs 5 elems]...[ETU 1 million elems]

arr[arr.length - 1]      ------> 1              -----> 1

let myPop = arr.pop()
arr.push(myPop)          ------> 2              -----> 2

arr.slice(-1).pop()      ------> 36             -----> 924  

arr.slice(-1)[0]         ------> 36             -----> 924  

[...arr].pop()           ------> 120            -----> ~21,000,000 :)

The last three options, ESPECIALLY [...arr].pop(), get VERY much worse as the size of the array increases. On a machine without the memory limitations of my machine, [...arr].pop() probably maintains something like it's 120:1 ratio. Still, no one likes a resource hog.

Florist answered 9/8, 2018 at 9:33 Comment(1)
If initial array can be empty, this approach will result incorrectly and [] will be turned into [undefined]. You need to protect backward push with explicit undefined check, something like myPop !== undefined && arr.push(myPop)Parkman
A
24

Just putting another option here.

loc_array.splice(-1)[0] === 'index.html'

I found the above approach more clean and short onliner. Please, free feel to try this one.

Note: It will modify the original array, if you don't want to modify it you can use slice()

loc_array.slice(-1)[0] === 'index.html'

Thanks @VinayPai for pointing this out.

Americium answered 5/11, 2019 at 9:57 Comment(4)
According to the comment by stackoverflow.com/users/510036/qix-monica-was-mistreated on this post #9050845 and the tests at jsperf.com/last-array-element2 that is extremely slowAnalcite
The .slice(-1) answer was already given multiple times, starting in 2012, and its implications were discussion in detail (unlike here). Please do not give repetitive answers just to get some upvotes.Gilus
@DanDascalescu Thank you for your kind words. It was honest mistake, I didn't saw that answer before on same question and tried to help with what I know. Also if upvotes were my moto then you would have seen more duplicate answers on my profile.Americium
@DanDascalescu Any way, way to encourage new members on the platform and a very great way to show their mistakes. Kudos to you man. Coming from such a strong profile, advocate, co-founder is very inspiring and I surely try not to follow such influencer and keep my ways polite enough to make new members comfortable. Thanks for the lesson. It was good one ;)Americium
P
22

Here's more Javascript art if you came here looking for it

In the spirit of another answer that used reduceRight(), but shorter:

[3, 2, 1, 5].reduceRight(a => a);

It relies on the fact that, in case you don't provide an initial value, the very last element is selected as the initial one (check the docs here). Since the callback just keeps returning the initial value, the last element will be the one being returned in the end.

Beware that this should be considered Javascript art and is by no means the way I would recommend doing it, mostly because it runs in O(n) time, but also because it hurts readability.

And now for the serious answer

The best way I see (considering you want it more concise than array[array.length - 1]) is this:

const last = a => a[a.length - 1];

Then just use the function:

last([3, 2, 1, 5])

The function is actually useful in case you're dealing with an anonymous array like [3, 2, 1, 5] used above, otherwise you'd have to instantiate it twice, which would be inefficient and ugly:

[3, 2, 1, 5][[3, 2, 1, 5].length - 1]

Ugh.

For instance, here's a situation where you have an anonymous array and you'd have to define a variable, but you can use last() instead:

last("1.2.3".split("."));
Pentangular answered 16/9, 2018 at 0:8 Comment(0)
P
22

ES6 object destructuring is another way to go.

const {length, [length-1]: last}=[1,2,3,4,5]
console.log(last)

You extract length property from Array using object destructuring. You create another dynamic key using already extracted key by [length-1] and assign it to last, all in one line.

Periosteum answered 9/3, 2020 at 17:24 Comment(3)
Thanks, Can you explain what exactly it does ?Yamen
from my understanding (I could be wrong) length is the first index of the array. but [length-1] is the last index (the one before it). :last is the alias used to define the last index (or the one before the first one to be exact)Uncouple
@TarunNagpal arrays are like objects, they have a length property and indices as properties. here we destructor length then use computed property name [length -1] to get the last element.Mut
D
21

For those not afraid to overload the Array prototype (and with enumeration masking you shouldn't be):

Object.defineProperty( Array.prototype, "getLast", {
    enumerable: false,
    configurable: false,
    writable: false,
    value: function() {
        return this[ this.length - 1 ];
    }
} );
Derosier answered 2/9, 2012 at 17:32 Comment(0)
H
20

I generally use underscorejs, with it you can just do

if (_.last(loc_array) === 'index.html'){
  etc...
}

For me that is more semantic than loc_array.slice(-1)[0]

Holusbolus answered 7/1, 2014 at 17:40 Comment(0)
N
19

jQuery solves this neatly:

> $([1,2,3]).get(-1)
3
> $([]).get(-1)
undefined
Newman answered 21/5, 2013 at 10:28 Comment(0)
A
19

ECMA 2022

With ECMA 2022 you have a new property at(). To get the last element from a Array or a string you can use at with the negative index -1. [1,2,3].at(-1). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at

If you like more fluent like arr.last to receive the last item you can define your own property to the array object.

if (!Array.prototype.hasOwnProperty("last")) {
  Object.defineProperty(Array.prototype, "last", {
    get() {
      return this.at(-1);
    }
  });
}

a = [1,2,3];
console.log(a.last);
Arabele answered 8/1, 2023 at 22:13 Comment(0)
T
15

To prevent removing last item from origin array you could use

Array.from(myArray).pop()

Mostly supported of all browsers (ES6)

Trexler answered 14/5, 2019 at 12:9 Comment(0)
F
14

In ECMAScript proposal Stage 1 there is a suggestion to add an array property that will return the last element: proposal-array-last.

Syntax:

arr.lastItem // get last item
arr.lastItem = 'value' // set last item

arr.lastIndex // get last index

You can use polyfill.

Proposal author: Keith Cirkel(chai autor)

Favorable answered 30/8, 2018 at 19:31 Comment(0)
K
13

Whatever you do don't just use reverse() !!!

A few answers mention reverse but don't mention the fact that reverse modifies the original array, and doesn't (as in some other language or frameworks) return a copy.

var animals = ['dog', 'cat'];

animals.reverse()[0]
"cat"

animals.reverse()[0]
"dog"

animals.reverse()[1]
"dog"

animals.reverse()[1]
"cat"

This can be the worst type of code to debug!

Khano answered 14/4, 2019 at 9:13 Comment(2)
If you do want a reversed copy of your array, you can use the spread operator now. e.g. [...animals].reverse()Stroh
you can simply copy the array before using reverse [1,3,4,5,"last"].slice().reverse()[0]Hildegaard
S
13

I think this should work fine.

var arr = [1, 2, 3];
var last_element = arr.reverse()[0];

Just reverse the array and get the first element.

Edit: As mentioned below, the original array will be reversed. To avoid that you can change the code to:

var arr = [1, 2, 3];
var last_element = arr.slice().reverse()[0];

This will create a copy of the original array.

Snatch answered 29/3, 2020 at 20:9 Comment(3)
This will alter the original arrayAcceptor
The slice() copies the array var arr = [1, 2, 3]; last_element = arr.slice().reverse()[0];Snatch
@Zellius Might as well just pop the last element if you're going to slice the array. i.e. arr.slice().pop()Cattleya
T
12

Personally I would upvote answer by kuporific / kritzikratzi. The array[array.length-1] method gets very ugly if you're working with nested arrays.

var array = [[1,2,3], [4,5,6], [7,8,9]]
​
array.slice(-1)[0]
​
//instead of 
​
array[array.length-1]
​
//Much easier to read with nested arrays
​
array.slice(-1)[0].slice(-1)[0]
​
//instead of
​
array[array.length-1][array[array.length-1].length-1]
Turbot answered 3/3, 2016 at 12:53 Comment(0)
K
10

You can add a last() function to the Array prototype.

Array.prototype.last = function () {
    return this[this.length - 1];
};

EDIT:

You can use a Symbol to avoid incompatibility with other code:

const last = Symbol('last');
Array.prototype[last] = function() {
    return this[this.length - 1];
};

console.log([0, 1][last]());
Kinata answered 20/7, 2015 at 8:21 Comment(1)
If you’re going to extend built-in prototypes or polyfill a property (i.e. monkey-patch), please do it correctly: for forward compatibility, check if the property exists first, then make the property non-enumerable so that the own keys of constructed objects aren’t polluted. For methods, use actual methods. My recommendation: follow these examples which demonstrate how to add a method that behaves like other built-in methods, as closely as possible.Cannady
W
10

As per ES2022, You can use Array.at() method which 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.

Demo :

const href = 'www.abc.com/main/index.html';
const loc_array = href.split('/');

// To access elements from an array we can use Array.at()
console.log(loc_array.at(-1)); // This will return item at last index.
Wrest answered 23/2, 2022 at 18:7 Comment(0)
F
9

You could add a new property getter to the prototype of Array so that it is accessible through all instances of Array.

Getters allow you to access the return value of a function just as if it were the value of a property. The return value of the function of course is the last value of the array (this[this.length - 1]).

Finally you wrap it in a condition that checks whether the last-property is still undefined (not defined by another script that might rely on it).

Object.defineProperty(Array.prototype, 'last', {
    get : function() {
        return this[this.length - 1];
    }
});

// Now you can access it like
[1, 2, 3].last;            // => 3
// or
var test = [50, 1000];
alert(test.last);          // Says '1000'

Does not work in IE ≤ 8.

Footrope answered 6/7, 2014 at 19:27 Comment(1)
Array.prototype.last is always undefined? The if isn't working under Chrome 36Hegumen
R
8

EDITED:

Recently I came up with one more solution which I now think is the best for my needs:

function w(anArray) {
  return {
    last() {
      return anArray [anArray.length - 1];
    };
  };
}

With the above definition in effect I can now say:

let last = w ([1,2,3]).last();
console.log(last) ; // -> 3

The name "w" stands for "wrapper". You can see how you could easily add more methods besides 'last()' to this wrapper.

I say "best for my needs", because this allows me to easily add other such "helper methods" to any JavaScript built-in type. What comes to mind are the car() and cdr() of Lisp for instance.

Ravo answered 18/3, 2018 at 18:50 Comment(2)
Why use a wrapper? If you have to call a w function just make the function return the last item.Tweeter
w([1,2,3]).length is undefined. w([1,2,3])[1] is undefined. Does not seem like a wrapper to me. And there is a syntax error. You have an extra ';'. See https://mcmap.net/q/45725/-trim-specific-character-from-a-string for how to write a class wrapper (SutString class) and use reflection to populate that wrapper. Though, imho, wrappers are overkill. Better to use encapsulation, like you almost have. return { arr: anArray, last() { return anArray[anArray.length - 1]; } };. Also, w is way too generic. Call is ArrayW or something.Starstudded
B
7

I think the easiest to understand for beginners and super inefficient way is: 😆

var array = ['fenerbahce','arsenal','milan'];
var reversed_array = array.reverse(); //inverts array [milan,arsenal,fenerbahce]
console.log(reversed_array[0]) // result is "milan".
Beaufort answered 27/10, 2014 at 3:32 Comment(2)
This solution takes O(n) more memory and takes O(n) time. It's really not the ideal solution.Gallnut
it must not start with fenerbahce. it must be like that: ['besiktas','galatasaray','trabzonspor','bursaspor','fenerbahce'] ;)Cameroncameroon
J
7

Functional programming with Ramda

If you're using JS, I would suggest checking out Ramda which is a functional-programming library (like Lodash and Underscore, except more advanced and modular). Ramda provides this with R.last

import * as R from 'ramda';
R.last(['fi', 'fo', 'fum']); //=> 'fum'
R.last([]); //=> undefined

R.last('abc'); //=> 'c'
R.last(''); //=> ''

It further provides init, head, tail. List monster from (Learn You a Haskell)

List Monster

Jeffers answered 31/12, 2018 at 15:1 Comment(15)
including library is not reasonable for getting last element, if I do, I would use underscorejs.org/#lastSoileau
@Soileau Ramda is a newer more modern and modular version of Lodash which is the replacement for Underscore.jsJeffers
yes, I tried ramda it tasted a bit not necessary overcomplicated at the first glance for me. Maybe I still don't think functional enough and will get into it when my mind will be ready for it. By the way, I see you have experience with it, how would look such code in ramda? _.chain([1,2,3]).map((val)=> { return val*2 }).first().value() -> result is 2. Does it support chaining ? I see ramda has method chain, but it looks like it's for smth elseSoileau
@Soileau Like this R.pipe(R.take(1), x=>x*2) (also works with typescript)Jeffers
would this code require more evil nesting if we add up more chaining? E.g.__.chain([1,2,3]).map((val)=> { return val*2 }) .filter((val)=> { return val > 3; }) .map((val)=> { return val*2 }) .first() .value() - paste.debian.net/1061022 (please see link with formatted code) - result is 8Soileau
No, Pipe takes more than one function const m = x => y => x * y; R.pipe(R.take(1), m(2), m(3), m(4)) What's the point here? I mean I'm down for helping you to learn Ramda but this has 0 to do with my answer? And it seems like you're a little bitter that you're struggling to grok Ramda so you downvoted me (not a good way to start a conversation). Keep on learning though. Btw, you can also do x = R.pipe( R.take(1), y=>y*2 ); y = R.pipe( x, z => z*2 )Jeffers
whatever trevor, unfortunately there is no way to take this down back. I'm going to upvote another your answer if it makes you feel better. By the way I don't try to learn it now, I just tried to highlight the thing what ramda misses and which kept me in Underscore/Backbone. Defining another function in temp variable is messing around instead of hiding things inside chaining.Soileau
You don't have to do that in fact, I would never do that for your case I would just pipe more than one thing. The point here is that ramda is doing function composition with pipe. And what Lodash is doing is wrapping an object in a base class that provides operators as methods. The Lodash method is a very bad idea. The reason why they do it is because legacy code that uses Lodash. For example, Rxjs, used to do things that way but now they use the pipe method too.Jeffers
One of the great practical upsides of the pipe method is that any library can export functions that work with pipe and that you only need to import what you're using. In addition anything imported that you're not using is subject to "tree shaking" which Webpack can actually remove in a bundle (dead code goes away). This makes it the Ramba method more-pure (functionally), more concise (look at my example), faster (no wrapping of objects), and smaller (no need to import a class, or all of the operators, and you can remove operators you don't use automagically)Jeffers
@Soileau if with can't take back" you mean a downvote, off course you can. If the user edits the answer, you can then retract the downvote.Eleni
Thank you one more time. So it looks functional programming has many sides, ramda just preaches one more way I didn't know before. Though not sure about badness of chaining. It's already into the core of ES6. E.g. [1,2,3].filter((val)=> { return val > 1; }).map((val) => { return val*2; }).push() -> yields 2 . I started this conversion at all because I remember myself wondering a few years ago when I wanted to switch to ramda and didn't find such necessity in FP as chaining IMHO. Being modular and advanced is fine(if it's really so), though I would stake on convenience of usage.Soileau
@Soileau but the evilness of that method despite ES6's adoption is pretty apparent, for example to find the keys of an object you don't do a.keys(), you do Object.keys(a)? Why? Because likely somewhere someone extended Object.prototype to already have keys and es didn't want to break backwards compat. This isn't a problem though with the Ramda method. R.pipe(R.keys, R.join(''))( {foo:1,bar:2} ); You just compose functions together.Jeffers
Moreover, with ramda and lodash (and hopefully not es6) people create libraries to extend core functionality. Extending prototype is generally considered bad. That's why it's kind of funny that the lodash team thought it was a good idea to recreate that problem by making all objects that their operators take instances of the wrapper class. (which any extension of lodash would have to monkey patch to).Jeffers
I don't understand why this answer got so many downvotes! Ramda is arguably better than both Lodash and Underscore. It is purely functional and clean even though it might be a bit hard to understand if someone is not used to functional programming. Its definitely a good answer to the problem though I still wouldn't recommend using a library if the only thing you have to do is to get the last element in an array.Sinclare
Beyond the scope of the question. Lodash and Underscore, included. Ramda is full of abbreviations and jargon. Better suited to use an actual functional language + llvm / emscripten to produce web assembly. Which is still out of scope.Starstudded
P
6

I'll suggest to create helper function and reuse it every time, you'll need it. Lets make function more general to be able to get not only last item, but also second from the last and so on.

function last(arr, i) {
    var i = i || 0;
    return arr[arr.length - (1 + i)];
}

Usage is simple

var arr = [1,2,3,4,5];
last(arr);    //5
last(arr, 1); //4
last(arr, 9); //undefined

Now, lets solve the original issue

Grab second to last item form array. If the last item in the loc_array is "index.html" grab the third to last item instead.

Next line does the job

last(loc_array, last(loc_array) === 'index.html' ? 2 : 1);

So, you'll need to rewrite

var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-2]))); 

in this way

var newT = document.createTextNode(unescape(capWords(last(loc_array, last(loc_array) === 'index.html' ? 2 : 1)))); 

or use additional variable to increase readability

var nodeName = last(loc_array, last(loc_array) === 'index.html' ? 2 : 1);
var newT = document.createTextNode(unescape(capWords(nodeName)));
Poundal answered 20/4, 2017 at 10:59 Comment(0)
P
6

Normally you are not supposed to mess with the prototype of built-in types but here is a hack/shortcut:

Object.defineProperty(Array.prototype, 'last', {
  get() {
    return this[this.length - 1]; 
  }
});

This will allow all array objects to have a last property, which you can use like so:

const letters = ['a', 'b', 'c', 'd', 'e'];
console.log(letters.last); // 'e'

You are not supposed to mess with a built-in type's prototype because you never when a new ES version will be released and in the event that a new version uses the same property name as your custom property, all sorts of breaks can happen. Also, it makes it hard for others to follow your code, especially for people joining the team. You COULD make the property to something that you know an ES version would never use, like listLastItem but that is at the discretion of the developer.

Or you can use a simple method:

const getLast = (list) => list[list.length - 1];
const last = getLast([1,2,3]); // returns 3
Planoconvex answered 24/11, 2020 at 6:33 Comment(0)
X
6

Update - 27 October 2021 (Chrome 97+)

Proposal for Array.prototype.findLast is now on Stage 3!

Here's how you can use it:

const array = [1, 2, 3, 4, 5];

const last_element = array.findLast((item) => true);
console.log(last_element);

You can read more in this V8 blog post.

You can find more in "New in Chrome" series.

Xanthippe answered 31/1, 2022 at 13:42 Comment(0)
M
5

Using ES6/ES2015 spread operator (...) you can do the following way.

const data = [1, 2, 3, 4]
const [last] = [...data].reverse()
console.log(last)

Please notice that using spread operator and reverse we did not mutated original array, this is a pure way of getting a last element of the array.

Ment answered 17/3, 2017 at 19:14 Comment(2)
Reversing an entire array just to get the last element is super inefficient.Genteel
@slang, agree. If you are doing hundreds to millions operations then you have to consider not to do it this way, but if you have to do it only several time than nobody will notice that. This example provides 'pure' call without changing actual data array.Ment
A
5

Using lodash _.last(array) Gets the last element of array.

data = [1,2,3]
last = _.last(data)
console.log(last)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Ation answered 20/9, 2017 at 20:31 Comment(0)
R
5

How about something like below:

if ('index.html' === array[array.length - 1]) {  
   //do this 
} else { 
   //do that 
}

If using Underscore or Lodash, you can use _.last(), so something like:

if ('index.html' === _.last(array)) {  
   //do this 
} else { 
   //do that 
}

Or you can create your own last function:

const _last = arr => arr[arr.length - 1];

and use it like:

if ('index.html' === _last(array)) {  
   //do this 
} else { 
   //do that 
}
Rosierosily answered 31/1, 2019 at 12:13 Comment(0)
S
4

Will this work?

if (loc_array.pop() == "index.html"){
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-3])));
}
else{
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-2])));
}
Searchlight answered 9/7, 2010 at 19:49 Comment(3)
No because .pop() returns the last element and also removes it, so your indexes change.Goggin
If you do not want your original array to be mutated then do arr.slice().pop() - this creates a new arrayRomona
better when you don't care about array anymore!Thunderpeal
V
4

This method will not mess with your prototype. It also guards against 0 length arrays, along with null/undefined arrays. You can even override the default value if the returned default value might match an item in your array.

const items = [1,2,3]
const noItems = []

/**
 * Returns the last item in an array.
 * If the array is null, undefined, or empty, the default value is returned.
 */
function arrayLast (arrayOrNull, defVal = undefined) {
  if (!arrayOrNull || arrayOrNull.length === 0) {
    return defVal
  }
  return arrayOrNull[arrayOrNull.length - 1]
}

console.log(arrayLast(items))
console.log(arrayLast(noItems))
console.log(arrayLast(null))

console.log(arrayLast(items, 'someDefault'))
console.log(arrayLast(noItems, 'someDefault'))
console.log(arrayLast(null, 'someDefault'))
Valdovinos answered 27/10, 2018 at 22:46 Comment(0)
P
4

This can be done with lodash _.last or _.nth:

var data = [1, 2, 3, 4]
var last = _.nth(data, -1)
console.log(last)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Premarital answered 22/11, 2018 at 6:26 Comment(0)
P
3

You can achieve this issue also without extracting an array from the url

This is my alternative

var hasIndex = (document.location.href.search('index.html') === -1) ? doSomething() : doSomethingElse();

!Greetings¡

Plotter answered 15/9, 2014 at 2:55 Comment(0)
A
3

This is clean and efficient:

let list = [ 'a', 'b', 'c' ]

(xs => xs[xs.length - 1])(list)

If you install a pipe operator using Babel it becomes:

list |> (xs => xs[xs.length - 1])
Aplomb answered 11/12, 2017 at 10:5 Comment(1)
I love that iife syntax so much. Thank you for making my life happily more complicated.Miele
S
3

Another ES6 only option would be to use Array.find(item, index)=> {...}) as follows:

const arr = [1, 2, 3];
const last = arr.find((item, index) => index === arr.length - 1);

little practical value, posted to show that index is also available for your filtering logic.

Sunflower answered 14/1, 2018 at 19:32 Comment(0)
C
3

Update 2020

Array.prototype.last = function(){
    return this[this.length - 1];
}

let a = [1, 2, 3, [4, 5]];

console.log(a.last());
// [ 4, 5 ]
console.log(a.last().last());
// 5

Setter and Getter

Array.prototype.last = function(val=null) {
  if (this.length === 0) {
    if (val) this[0] = val;
    else return null; 
  }
  
  temp = this;
  while(typeof temp[temp.length-1] === "object") {
    temp = temp[temp.length-1];
  }
  
  if (val) temp[temp.length-1] = val; //Setter  
  else return temp[temp.length-1]; //Getter
  
}

var arr = [[1, 2], [2, 3], [['a', 'b'], ['c', 'd']]];
console.log(arr.last()); // 'd'
    
arr.last("dd"); 
console.log(arr); // [ [ 1, 2 ], [ 2, 3 ], [ [ 'a', 'b' ], [ 'c', 'dd' ] ] ]
Cathepsin answered 25/10, 2020 at 6:50 Comment(3)
Please avoid polluting prototypes.Blowtorch
@Sean, adding is a better practice compare to rewriting prototype.Cathepsin
I don't know what you're trying to say but modifying prototypes you don't own makes your code prone to conflicts and hurts forward-compatibility. Prototype pollution is a known bad practice caught by JavaScript security bulletins.Blowtorch
D
2

The arrow function makes the fastest-performing method more concise, by not repeating the name of the array.

var lastItem = (a => a[a.length - 1])(loc_array);
Duhamel answered 3/8, 2017 at 0:24 Comment(2)
But why write a method when you can access the last item directly... var lastItem = a[a.length-1]Gorga
This doesn't demonstrate creating a method, though. It shows off using an arrow function to "rename" loc_array to a within the context of the function. It's like doing var getLast = a => a[a.length - 1]; var lastItem = getLast(loc_array), but the "getLast" function is in-lined, not separately defined.Matronage
B
2
var str = ["stackoverflow", "starlink"];
var last = str[str.length-1];//basically you are putting the last index value into the array and storing it in la
Blackwood answered 7/4, 2021 at 1:14 Comment(0)
N
1

There is also a npm module, that add last to Array.prototype

npm install array-prototype-last --save

usage

require('array-prototype-last');

[1, 2, 3].last; //=> 3 

[].last; //=> undefined 
Newsman answered 28/7, 2017 at 6:5 Comment(4)
source of function?Electrostatics
it's simalar to this? Array.prototype.last = function(){ return this[this.length - 1]; } + Object.defineProperty(Array.prototype, 'last', {enumerable: false});Electrostatics
in your example last is function you should call it like ['a', 'b'].last() // 'b', while in module last is property and you can call it like ['a', 'b'].last // 'b'Newsman
ok it's a trik to remove () in code, but this "property" stay in fact a function called each time, right?Electrostatics
G
1

For a readable and concise solution, you can use a combination of Array.prototype.slice and destructuring.

const linkElement = document.getElementById("BackButton");
const loc_array = document.location.href.split('/');

// assign the last three items of the array to separate variables
const [thirdLast, secondLast, last] = loc_array.slice(-3);

// use the second last item as the slug...
let parentSlug = secondLast;

if (last === 'index.html') {
  // ...unless this is an index
  parentSlug = thirdLast;
}

const newT = document.createTextNode(
  unescape(
    capWords(parentSlug)
  )
);

linkElement.appendChild(newT);

But to simply get the last item in an array, I prefer this notation:

const [lastItem] = loc_array.slice(-1);
Generalization answered 11/4, 2020 at 12:44 Comment(0)
R
1

ES2023 Array Method findLastIndex

The findLastIndex() method iterates the array in reverse order and returns the index of the first element that satisfies the provided testing function. If no elements satisfy the testing function, -1 is returned.

const arr = [1,2,3,4];
const lastIndex = arr.findLastIndex(x => true);
console.log(arr[lastIndex]); // 4

PS: findLastIndex() method is supported by all browsers and on Node.js version 18+.
see browser compatibility

Ratline answered 9/6, 2023 at 21:32 Comment(1)
This is the best option if you actually need to know the index number, but if you just want the last element then it's simpler to just use arr.at(-1) (added in ES2022). See https://mcmap.net/q/44989/-get-the-last-item-in-an-arrayMegargee
E
0

Using reduceRight:

[3,2,1,5].reduceRight((a,v) => a ? a : v);
Ergosterol answered 4/4, 2016 at 12:4 Comment(2)
This is actually a pretty creative way of doing it, although it does run in O(n) time because it still traverses the whole array.Pentangular
If you don't mind, I made it even more concise by removing the unnecessary return and curly braces.Pentangular
U
0

simple answer

const array = [1,2,3]
array[array.length - 1]
Uncouple answered 14/8, 2020 at 18:48 Comment(1)
Very good answerAdios
S
0

The pop() and slice() both method are faster. You can use pop() method if you are fine with modifying the array. If you don't want to change the array, the slice() method can be used.

let arrItems = [12, 24, 60, 80, 10, 14, 123];
console.time('using array length');
let lastItem = arrItems[arrItems.length - 1];
console.log(lastItem);
console.timeEnd('using array length');

console.time('using slice method');
let lastItem1 = arrItems.slice(-1)[0];
console.log(lastItem1);
console.timeEnd('using slice method');

console.time('using pop method');
let lastItem2 = arrItems.pop();
console.log(lastItem2);
console.timeEnd('using pop method');

//Output:

//123
//using array length: 0.200ms
//123
//using slice method: 0.175ms
//123
//using pop method: 0.012ms
Speechmaking answered 16/8, 2023 at 8:7 Comment(0)
E
0

In case your indices are random strings, уоu can use this:

arr[Object.keys(arr)[Object.keys(arr).length - 1]]
Etesian answered 23/8, 2023 at 19:2 Comment(0)
G
0

You can use snippet that extends the functionality of arrays by adding a new method called last(). This method can be used various approach to retrieve the last item of an array. Choose one of the many possibilities:

Array.prototype.last = function() {
  return this[this.length - 1]
  // return this.slice(-1)[0]
  // return this.at(-1)
  // return this.findLast(x => true)
  // return [...this].reverse()[0]
  // return this.reduceRight(_ => _)
  // return this.slice().reverse()[0]
  // return this.pop()
  // return this.splice(-1,1)[0]
  // return [...this].pop()
  // return this.find((_,i,a)=>a.length==i+1)
}


console.log([2,4,6].last()) // 6
console.log([1, 2, 3].last()) // 3
Geyserite answered 31/8, 2023 at 17:32 Comment(0)
W
-1

The simple way to get last item of array:

var last_item = loc_array.reverse()[0];

Of course, we need to check to make sure array has at least one item first.

Wagonage answered 22/11, 2018 at 2:28 Comment(4)
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. - From ReviewRasping
The question is "How to get last item in an array", and my solution should works. :)Wagonage
this is the slowest way to get the last element... what if the array has a million elements?Dixson
Terrible terrible idea! reverse changes the original array so if you run this twice in a row you get different results (asusming length > 1)Khano
F
-4

to access the last element in array using c# we can use GetUpperBound(0)

(0) in case if this one dimention array

my_array[my_array.GetUpperBound(0)] //this is the last element in this one dim array
Fritzsche answered 25/10, 2019 at 3:52 Comment(1)
The question was how to do it in JavaScript :)Beetner
I
-6
array.reverse()[0]

That's so simple

Indispensable answered 31/7, 2019 at 8:41 Comment(2)
Reverse modifies the original array. You should call Array.from(items).reverse()[0] for this method.Starstudded
This produces such an unnecessary overhead. Even with the suggestion of @Starstudded it's still bad, I wouldn't use it even for an array that is guaranteed to have no more than two items.Viewable

© 2022 - 2024 — McMap. All rights reserved.