"indexOf" should be "firstIndexOf"

"indexOf" is essentially "firstIndexOf". Especially given the fact that the "lastIndexOf" property exists.

It would be extemely logical to have "firstIndexOf" and "lastIndexOf" properties.

[1, 2, 3, 4, 2, 5].indexOf(2); // 1 although "4" should also be applicable
[1, 2, 3, 4, 2, 5].firstIndexOf(2); // Uncaught TypeError [1,2,3,2,4].firstIndexOf is not a function

In my opinion, both "indexOf" and "firstIndexOf" should be working as it is logical.

Hi!

In my opinion, both "indexOf" and "firstIndexOf" should be working as it is logical.

I disagree. It might be unfortunate that indexOf wasn't named
firstIndexOf, but it would be confusing if there is more than one way
to do it
. I'd rather
follow the Zen of Python
in this regard, in that "there should be one -- and preferably only one
-- obvious way to do it".

It's bad enough already that we have .slice(), .substring() and
.substr() on strings.

kind regards,
Bergi

In my opinion, those who want to follow the Zen of Python generally prefer Python over JavaScript.

JavaScript clearly has multiple ways of doing things (for example "for (let a of b)" or "for ( let i = 0; i < b.length; i++ ) {}" or "b.map(element=>...)" etc.).

I don't think it is wise to pursuit "one way of doing things" when it is clear that the language allows multiple ways of doing things.

My personal opinion is that 'indexOf` is not ambiguous. It is natural to search a list starting from the front. I don't think that needs stating explicitly.

Other languages are the same, not needing to make the direction explicit:

2 Likes

My personal opinion is that 'indexOf` is not ambiguous. It is natural to search a list starting from the front. I don't think that needs stating explicitly.

In my opinion, it is, it is not and it does:)

I will explain: for a long time I didn't know that such thing as the "lastIndexOf" exists. It just didn't cross my mind that they could invent it. I think it has a lot to do with the way that I didn't know specifically how "indexOf" works (I usually used it to find the only element in the array and was satisfied with that).

But if the method was called "firstIndexOf" I would almost certainly ask myself: "Interesting: maybe there is a "lastIndexOf" as well?"

I would also like to add about ambiguity:

If you don't know that the method "lastIndexOf" exists then the "indexOf" method is ambiguous to you: there is a 50% change it means the first index and 50% chance it means the last. And as I've said: I'had been programming in JavaScript for years without even having a clue about the "lastIndexOf". I couldn't even Google it as I didn't know such a concept exists.

Regarding the no-such-thing-in-other-languages argument: on one hand it has some ground because it is easier when all languages behave in the same (or at least similar) way.

On the other hand it stops innovations altogether. Imagine some suggesting an improvement in Python and it getting dismissed because "no such thing in JavaScript". Then this person suggests this change in JavaScript and gets turned down because "no such thing in Python".

what's next, rename all Array methods such as find to findFirst ? I think with all the issue we have in JS, adding more aliases is not one to consider ... the language is already "bloated" with methods nobody uses, see the String prototype as example, keep adding aliases doesn't sound like a great suggestion, imho.

1 Like

I would also like to add one thing.

Adding "firstIndexOf" could also mean more clarity in the code.

array1.firstIndexOf(3) // We imply that there might be several "3"s in the array
array2.indexOf(3) // We imply that there is only one "3" in the array

Absolutely, that may have been a better name in the beginning. But, since we started out with just indexOf and added lastIndexOf 20+ years later, the only thing worse would be having both indexOf and firstIndexOf.

4 Likes

Why? I don't understand the desire not to add something. The idea that "there should be only one way to do things" has failed in JavaScript long ago - you can do everything in a million ways here. Which is also the advantage of the language and the reason for it's popularity (you type - it works. Not "you read the Zen of Python and hope you are not the heretic").

I also don't understand the claim: "We have a lot of methods that people don't use". And? We will run out of memory on hard drive, or what?

1 Like

JS. certainly embodies TIMTOWTDI - there is more than one way to do it. That said, adding aliases ends up confusing far more than it ends up helping, empirically, and it’s just never going to happen.

It has happened a lot during history. Current JavaScript is way different (and has more variety) than the one that was initially created in 10 days.

In my opinion, JavaScript is a 'universal' language, along with PHP, HTML, and CSS. Two qualities make it uniquely useful: that it is built into most browsers, and that new versions are mostly back-compatible with all previous versions, so that user code can continue to work well past the time that their creators are still around to fix or extend them. These qualities make these languages reliable as part of the Web infrastructure.

Finding a string in another string is a basic operation with a unique name, and that is enough to satisfy universality. 'indexOf' is an adequate name, and that is good enough. Note that it focuses on its output (it results in a character index) rather than its function (it searches for a string in another string) or its full details (it stops after the first match). A truly proper name would be unwieldy and lengthy ('searchForFirstStringInStringGivingIndex'), not suitable for a universal builtin function.

It is valuable to keep JavaScript stable, and not extend it unless the extension helps programming to become easier or better. A good example from PHP is 'foreach', which is a basic loop operation that gives an index and the value at that index to become far easier and more intuitive than it was before 'foreach' was added to the language. There are many such instances in JavaScript, particularly in its own loop operations.

Adding to any universal language should keep older ways of doing similar operations, so care should go into keeping the language stable and as simple as possible. Otherwise, the learning hurdle becomes too large and the language must be replaced by another, which is expensive in many ways.

I don't think this name is good enough because it is ambiguous! You don't know if this index is the first or the last.

@ljharb Every discussion you join, you attempt to stop people even discussing what would constitute progress.

Please please please stop doing that. It is not productive. I know your focus is on compatibility, but the language needs vision and direction. You are not interested in providing vision or direction, so I find it reprehensible that you make it so much harder for the people who DO have vision to work with each other to make things happen.

Once we know where we are trying to get to, THEN we can focus on the taking very conservative steps to get there, but YOU shut down the discussions of where we're trying to get to and it makes me angry.

You are correct. But you may not have read my post carefully. There is no reasonable name that can express all three of the important characteristics of this function! An identifier can often not state all the characteristics of the value or function named. All that is really required is that it be unique. All language keywords and essential library identifiers have to be learned. It is part of the hurdle of learning any programming language.

At the scale of JavaScript, and at the compatibility issues it's treading, every new feature added significantly harms the language and all its users by default. People often come to this discourse with the assumption "oh here's just a nice-to-have for me; how bad can it be?" but eventually they will never pass TC39; that's just how things work. It's okay to discuss in a vacuum how good or bad the feature, should it exist, can be, but the truth is, unless there's overwhelming evidence that there's an irrefutable need for engines (not libraries, not transpilers) to build it, it will not be built because of the harm-by-default principle.

every new feature added significantly harms the language and all its users by default

I agree! I'm actually pretty disappointed with the quality of recent work on the language. Each new feature feels like it's properly integrated with 2/3 of the other features in the language.

Take proxies for example, which are properly integrated with every language feature except private properties. Or take data freezing, which is implemented for the core object system but has no coherent definition for any of the exotic data types.

If I had my way I would freeze the spec for a year and bash everyone's heads together until the ideas we had already fully committed to felt stable and solid in relation to each other.

That would be more like a "designing a language" exercise, where I feel that we're currently stuck in "glue warts on the toad" mode.

You are implying that the committee doesn't have vision... Have you considered an important part of the vision is keeping the language coherent? As mentioned, adding features has a cost. Communicating the constraints early is not shutting people down, it's making it clear the constraints under which we have to operate.

The examples you take are actually coherent given the language that existed before it. Private fields are modelled around closure state associated with the identity of the receiver, which has never and should never become trappable by proxies. And by exotic data types I assume you mean internal state, which is beyond what freezing affects (there have been proposals about pure / side-effects free data access, but that's an extremely complex topic).

I'm not claiming all language features are perfect, and hindsight is always 20/20. Some decisions were historically made that ended up making later features more difficult and awkward to add. But that's exactly the reason we need to communicate the high cost of adding features, because sometimes something that looks simple and innocuous is anything but.

1 Like

I'm saying yes, the language could and should be more coherent.

I chose examples where I'm pretty certain I'm not wrong. I've already proven that proxies don't need to break at all when used on objects with private properties. It's just an oversight that no getReceiver trap is offered by proxies: New Proxy trap for method application - #2 by conartist6. It's not because of historical precedent. There was no historical reason not to add this support. There's no reason not to add it now either!

And by the way the way in terms of coherent vision, we have the unfreezable Map and Set implementations, but where's our (unfreezable) List!?