Проверьте, является ли имя свойства индексом массива

Я хочу назначить некоторые свойства массиву, но только если они являются индексами массива. В противном случае некоторые реализации могут переключить базовую структуру на хэш-таблицу, и я не хочу этого.

Например, это индексы массива: "0", "1", "2", "3", "4", "4294967294"

Но это не: "abcd", "0.1", "-0", "-1", " 2", "1e3", "4294967295"

Есть ли простой способ проверить, является ли строка индексом массива?

Ответ 1

В ECMAScript 5 индексы Array определяются следующим образом:

Имя свойства P (в виде значения String) представляет собой массив индекс тогда и только тогда, когда ToString (ToUint32 (P)) равен P и ToUint32 (P) не равно 2 32 -1.

(Определение в ECMAScript 2015 сформулировано иначе, но должно быть эквивалентным.)

Тогда код будет

function isArrayIndex(str) {
  return (str >>> 0) + '' === str && str < 4294967295
}

Шаг за шагом,

  • ToUint32 (P) можно сделать, сдвинув 0 бит с помощью без знакового оператора сдвига вправо

    P >>> 0
    
  • ToString (ToUint32 (P)) можно выполнить, объединив пустую строку с оператором добавления.

    (P >>> 0) + ''
    
  • ToString (ToUint32 (P)) равно P, можно проверить с помощью оператора strict equals.

    (P >>> 0) + '' === P
    

    Обратите внимание, что это также гарантирует, что P действительно был в виде значения String.

  • ToUint32 (P) не равно 2 32 -1 можно проверить с помощью оператора strict do-not-equal

    (P >>> 0) !== 4294967295
    

    Но как только мы знаем, что ToString (ToUint32 (P)) равно P, достаточно одного из следующих:

    P !== "4294967295"
    P < 4294967295