検証環境

  • Google Chrome 61.0.3163.100
  • Firefox 56.0

コード

下記コードを実行すると、期待通りの結果を返します。

console.log('abcd'.indexOf('abcd', 1));   // -1
console.log('abcd'.includes('abcd', 1));  // false

次に下記コードを実行すると、期待に反した結果が返ってきます。

console.log('abcd'.indexOf('abcd', -1));  // 0
console.log('abcd'.includes('abcd', -1)); // true

ECMAScript 2017

String.prototype.includes, String.prototype.indexOf の仕様を読むと、第二引数 positionToInteger() を通すことで整数化しています。

  1. Return the number value that is the same sign as number and whose magnitude is floor(abs(number)).

number-1 であった場合、abs(number) によって -11 となりますので、「'abcd'.indexOf('abcd', -1) と 'abcd'.indexOf('abcd', 1) の返り値は等価となるはず」と考えていますが、期待に反して、Google Chrome/Firefox は等価ではない挙動を示しています。

MDN

fromIndex Optional
呼び出す文字列内の検索を始めるための位置。整数を指定できる。デフォルトの値は 0。fromIndex <= 0 の場合、文字列全体が検索される。fromIndex >= str.length の場合、 文字列は検索されず -1 を返す。searchValue が空文字でない限り、str.length が返される。

MDNによれば、第二引数に負の数が指定された場合は 0 が指定されたのと同じ挙動となるようですが、仕様と異なる説明がされているように感じ、もやもやしています。

仕様をどのように解釈すれば良いのでしょうか。