r/learnjavascript • • Oct 26 '21

Negative array indexing using "at" method

Post image
203 Upvotes

69 comments sorted by

28

u/HyerOneNA Oct 26 '21

Why use the at method when you can just use square bracket notation?

6

u/jd_300 Oct 26 '21 edited Oct 26 '21

In bracket notation negative indexing is not possible but using at method you can easily navigate to the last index of array. It's just another way to access elements.

11

u/Gibbo3771 Oct 26 '21
const lastElement = arr[arr.length - 1]

Why wouldn't you just do the above?

17

u/ExclusiveOar Oct 26 '21

Preference. arr[-1] is allowed in other languages and it's a nice to have.

arr.at(-1) is arguable cleaner than arr[arr.length - 1]. Personally I wouldn't bother until JS eventually supports arr[-1].

1

u/[deleted] Oct 27 '21

arr.at(-1) is also constant time right?

1

u/ExclusiveOar Oct 27 '21

No expert here, but I would assume so.

But so is arr[arr.length - 1] because array.length isn't calculated here, its a prop already on the array.

You can see this by creating an array, console.log it and expand it in the console.

0

u/[deleted] Oct 26 '21

[deleted]

13

u/ExclusiveOar Oct 26 '21

Which will be largely irrelevant to the vast majority of people. I bet you do a ton of stuff in your code which will be more inefficient than this (not judging, it's the nature of high level languages).

Readability > performance, true for 999/1000 use cases (probably more).

To put it in perspective I was playing around with how efficient I could make FizzBuzz, for no reason what-so-ever. I had to calculate it for the numbers 1 - 1 000 000 000 to get meaningfully measurable time period (1.9 seconds) to try to optimise. I got it to about 0.85 seconds!

1 second saved, over a billion operations. Don't worry about performance until your app is slow, then look at your API calls before you consider anything else.

0

u/[deleted] Oct 26 '21

[deleted]

6

u/ExclusiveOar Oct 26 '21

And that's what makes it preference 🙂

2

u/Darmok-Jilad-Ocean Oct 26 '21

Because if you’re doing a map/filter/reduce/etc you have to first store that in a temporary variable and then reference the temp var twice to get the last element.

1

u/HyerOneNA Oct 26 '21

I mean this is what I meant..

0

u/[deleted] Oct 26 '21

cause its longer than const lastElement = arr.at(-1) ? also, no need for useless computations in source code

-1

u/HyerOneNA Oct 26 '21

But the at method isn’t widely available on all browsers.

12

u/nullol Oct 26 '21

No idea why you're being downvoted for asking a genuine question in r/learnjavascript - I am sure a lot of new developers would be confused by this as well.

7

u/HyerOneNA Oct 26 '21

Yup, idk. A lot of no lifers in here.

3

u/nullol Oct 26 '21

I think because it's Reddit people forget or don't realize what sub they're on and assume you're being intentionally contrary rather than trying to learn something new (I have been a JS developer for 8yrs and I never knew about this in other languages so TIL as well).

2

u/HyerOneNA Oct 26 '21

I’m coming from C++, so yeah. It’s a lil different lol.

18

u/senocular Oct 26 '21

Because fruits[-1] won't give you "avacado", it will give you undefined

-15

u/Gibbo3771 Oct 26 '21

fruits[fruits.length - 1]

This is what people mean, no one expects [-1] to work.

29

u/senocular Oct 26 '21

at() reduces the requirement to refer to your array twice. This can be useful when you're using it at the end of a longer expression.

fruits.map(toBarcode).filter(onSale).at(-1)

4

u/yadoya Oct 27 '21

The real tip is always in the comments

16

u/VikaashHarichandran Oct 26 '21

People coming from other scripting languages do expect

7

u/[deleted] Oct 26 '21

wouldnt it be nice to have though?

19

u/greymalik Oct 26 '21

People coming from Python or Ruby expect it.

-13

u/doyouseewhateyesee Oct 26 '21

people coming from python or ruby should read the docs

2

u/Mad-chuska Oct 26 '21

Also true

2

u/[deleted] Oct 26 '21

No idea why you're getting downvoted. When I'm switching to a different language I should learn differences not expect it to behave the same. After all if it would work exactly the same what would be the point of switching.

0

u/doyouseewhateyesee Oct 26 '21 edited Oct 26 '21

lol right. i’m not going to pick up python and start writing javascript methods

it’s comical that a comment recommending devs to read the docs in a learnjavascript subreddit is being downvoted. or don’t read the docs I guess, not my problem

-1

u/reaven3958 Oct 27 '21 edited Oct 27 '21

This whole notion seems hilariously ill advised. Basically it's letting you access the index from the end instead of the start (normally done using arr.length - i, where i = 1 is first valid index). Some JS methods do similar stuff, but not usually for accessing values. This conflicts with mountains of code using searches like Array.indexOf that anticipates a -1 to be the invalid index token. For a minimal reduction in boilerplate to satisfy a case thats relatively uncommon (how often do you really traverse an array backwards like this), it just feels like this is inviting all manner of mayhem. I imagine it'll start getting banned on company style guides in favor of traditional bracket notation sooner than later, if it isn't already.

Probably some neat party tricks you can do with it for the leetcode crowd tho.

56

u/[deleted] Oct 26 '21

Avocado*

46

u/Darmok-Jilad-Ocean Oct 26 '21

Make a JIRA ticket

21

u/nullol Oct 26 '21

No time. We gotta get this to production.

11

u/monsterbois Oct 26 '21

Wow, our product failed because of a misspelled word

7

u/starraven Oct 27 '21

Post mortem report, stat!

6

u/jayedeem Oct 27 '21

Be an interesting retro

4

u/Darmok-Jilad-Ocean Oct 27 '21

What went well: Teamwork!

What didn’t go well: Didn’t meet sprint goal

What we can improve: Other teams did bad stuff!

33

u/[deleted] Oct 26 '21 edited Oct 26 '21

FYI, doesn't work on Edge 18 and below, IE and SafarIE (20% of users theoretically use these)

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at#browser_compatibility

16

u/ElllGeeEmm Oct 26 '21

Thank God for webpack

7

u/samanime Oct 26 '21

Or Babel.

4

u/undercontr Oct 26 '21

Or core-js

19

u/queen-adreena Oct 26 '21

IE doesn’t support flex, scrolling, or the colour green either. Who cares.

5

u/[deleted] Oct 26 '21

Me, one of the bigger clients using my company's SaaS uses IE. Throwing money away to not support them atm.

9

u/[deleted] Oct 26 '21

Yeah, and if someone is using IE I don't want them on my website

4

u/snyderling Oct 26 '21

fruits.slice(-1)[0] is a another (more backwards compatible) way to do it

6

u/Dodgy-Boi Oct 26 '21

array.reverse()[0]

5

u/NekkidApe Oct 27 '21

In case anyone is using this... It's mutating the original array

1

u/Dodgy-Boi Oct 27 '21

I saw a huge battle about index. And came up with another solution (I honestly tried to make it as ridiculous and/or unique as possible).

2

u/NekkidApe Oct 27 '21

Maybe reverse and shift then for extra points

2

u/[deleted] Oct 27 '21

Too slow, unfortunately. Accessing a value in an array using an index should be in O(1) time complexity.

2

u/Dodgy-Boi Oct 27 '21

I am front end. My calculations are happening on client. I don’t care about either users with old devices nor your O nor your o nor * of yours; all I care about is the ( . Y . ) (not necessarily yours)

partially /s

2

u/Notimecelduv Oct 28 '21

I don't get why people are upvoting this post.

1

u/delventhalz Oct 26 '21

This is nice, but I kind of just want a last method. That would solve 99% of the use cases I might use at for.

While I’m at it, head and tail would be nice too (though brackets/slice work well enough for those).

4

u/_inz_ Oct 26 '21

Miss this so much coming from Swift

1

u/gigraz_orgvsm_133 Oct 26 '21

wouldn't fruits[fruits.length - 1] work?

4

u/delventhalz Oct 26 '21

In some cases. Not if you are chaining. And it is tedious in all cases.

1

u/Notimecelduv Oct 28 '21

If you're chaining methods, you can just use the arr argument in the callback function.

2

u/delventhalz Oct 28 '21

That doesn't really apply here. Say you are trying to filter a list of numbers to just be even numbers, and then grab the last one. The arr parameter in filter would not help you. You would need an intermediate variable.

const evens = nums.filter(n => n % 2 === 0);
const lastEven = evens[evens.length - 1];

You could chain on a reduce and use that arr just to grab the last one. That is super hacky though, and extremely wasteful.

const lastEven = nums
  .filter(n => n % 2 === 0)
  .reduce((_, __, ___, arr) => arr[arr.length - 1]);

However, a last or at method would allow you to do this without the intermediate variable, and without the weird hacky extra iteration in the reduce.

const lastEven = nums
  .filter(n => n % 2 === 0)
  .last();

1

u/Inevitable-Weekend-4 Oct 27 '21

welcome to python

1

u/[deleted] Oct 27 '21

🥑

1

u/gniziemazity Oct 27 '21

It's always interesting to see how languages evolve, but not so great when the update only affects some browsers... I usually keep it safe and use established features only.

1

u/warpedspockclone Oct 27 '21

array.slice(-1)

1

u/Notimecelduv Oct 28 '21

arr.slice(-1)[0]

0

u/[deleted] Oct 26 '21

[deleted]

3

u/Tintin_Quarentino Oct 26 '21

It reduces shit

1

u/stickybobcat Oct 27 '21

Is this a joke?

0

u/[deleted] Oct 26 '21

[deleted]

5

u/great_site_not Oct 26 '21

For lots of people, when they come from a language like Python where you can just do array[-1], having to write out array[array.length - 1] every time is a genuine annoyance. It's a phrase that people have to write pretty frequently, it's nice to have shorthand.

2

u/technicallynick Oct 26 '21

That's fair. However -1 is used to signify that the index wasn't found for the item you're searching for in most cases. I'm just seeing this as muddying the waters.

0

u/[deleted] Oct 26 '21

go back to assembly then

0

u/[deleted] Oct 26 '21

[deleted]

1

u/[deleted] Oct 27 '21

Cause you can express simple stuff in complex ways, obviously.

Instead of just writing "at(-1)" - you can write over 20 lines of code with weird register check operators and jumps and all that good stuff!