0

why this is happening in javascript?

'abc'.indexOf('a');        //0
'abc'.indexOf('');         //0

while in the other falsy values, the value is -1:

'abc'.indexOf();           //-1
'abc'.indexOf(false);      //-1
'abc'.indexOf(undefined);  //-1

i have seen also those questions:
Q1 didnt understand the answer in depth.
Q2 in java and not javascript.

ofir_aghai
  • 3,017
  • 1
  • 37
  • 43
  • `"false".indexOf(false)` is 0. – Niet the Dark Absol Oct 03 '18 at 09:45
  • And `"undefined".indexOf()` is also 0. – Niet the Dark Absol Oct 03 '18 at 09:46
  • While the duplicate is about the Java programming language, the answer applies to this question. – nbokmans Oct 03 '18 at 09:46
  • @nbokmans this is javascript – You Nguyen Oct 03 '18 at 09:46
  • @NguyễnThanhTú Yes. And the answer applies here because it's about strings, not the language used. – Niet the Dark Absol Oct 03 '18 at 09:47
  • Well, by standard, 4th step of `indexOf` implementation is calling `toString` on first argument. So it looks for `"undefined"` string in given string. More [here](https://www.ecma-international.org/ecma-262/6.0/#sec-string.prototype.indexof) – Andrey Oct 03 '18 at 09:47
  • 3
    The answer (for JavaScript and for Java) is basically: Because that's how the function is specified to behave. For JavaScript, [details here](https://tc39.github.io/ecma262/#sec-string.prototype.indexof). Fundamentally, if the start position (0 in your example) plus the length of the search string (0) isn't greater than the length of the string you call it on (0), it loops checking code units. Since there are no code units to check, and 0 + 0 isn't greater than 0, the result is 0. – T.J. Crowder Oct 03 '18 at 09:55
  • 2
    Is it a really good idea to like that question as duplicate to one of a different language? I mean the fundamental idea might be the same, but it would not be the first time that the reason why (the specs) for that behavior are different for another language. I mean Java and JavaScript could use two different approaches to handle/specify this. – t.niese Oct 03 '18 at 09:57
  • 1
    @T.J.Crowder fixed. – ofir_aghai Oct 03 '18 at 10:01
  • @t.niese - Yeah, I'm not convinced either. [It's been done before](https://stackoverflow.com/questions/28692565/why-javascript-indexof-empty-string-always-returning-zero), too. – T.J. Crowder Oct 03 '18 at 10:04

1 Answers1

4

The answer, fundamentally, is: Because that's how the function is specified to behave. And it makes sense, from a certain perspective.

The main bit related to returning 0 when you search for an empty string is this:

Return the smallest possible integer k not smaller than start such that k + searchLen is not greater than len, and for all nonnegative integers j less than searchLen, the code unit at index k + j within S is the same as the code unit at index j within searchStr; but if there is no such integer k, return the value -1.

Since the length of the search string is 0, both halves of that "and" are satisfied by k = 0: k + searchLen is not greater than the length of the string, and for all nonnegative integers less than the search length (there are zero), the code points match.

Or roughly speaking, in code:

function indexOf(searchString, position = 0) {
    let s = String(this);
    let searchStr = String(searchString);
    let len = s.length;
    let start = Math.min(Math.max(position, 0), len);
    let searchLen = searchStr.length;
    let k = 0;
    while (k + searchLen <= len) {
        if (s.substring(k, k + searchLen) === searchStr) {
            break;
        }
        ++k;
    }
    const found = k + searchLen <= len;
    return found ? k : -1;
}

Since k + searchLen (0) is <= len (0), k (0)` is returned.

Live Example:

function indexOf(searchString, position = 0) {
    let s = String(this);
    let searchStr = String(searchString);
    let len = s.length;
    let start = Math.min(Math.max(position, 0), len);
    let searchLen = searchStr.length;
    let k = 0;
    while (k + searchLen <= len) {
        if (s.substring(k, k + searchLen) === searchStr) {
            break;
        }
        ++k;
    }
    const found = k + searchLen <= len;
    return found ? k : -1;
}

console.log(indexOf.call("abcd", ""));

Another way to look at it is this answer related to Java...or to life in general.


Re your question passing in non-strings: One of the first steps is:

Let searchStr be ? ToString(searchString).

...which is let searchStr = String(searchString); in my rough code above. That means false becomes "false" and undefined becomes "undefined". "abc" doesn't contain either "false" or "undefined".

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875