`if (0 in array)` - это даже законно?

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

if ('field' in object) {
    /* Do something with object.field */
}

чтобы определить, что переменная с именем field действительно существует в object, даже если она равна undefined.

И мой Firefox Developer Edition 44 может определить, есть ли поле в массиве, подобном этому:

if (0 in array) {
    /* Do something with first element */
}

Вопрос: этот метод легален? Является ли это частью жизненного стандарта или нет?


Что он должен делать:
Пусть q - массив с такими элементами:

[ 5, <1 empty slot>, undefined, 5 ]

Тогда:

  • 0 in q, 2 in q, 3 in q равно true;
  • 1 in q соответствует false.

Ответы

Ответ 1

if (0 in array) - это даже законно?

Конечно. Оператор in проверяет, существует ли свойство в объекте (напрямую или через цепочку прототипов). Левый операнд - это имя свойства, правый объект - это объект для проверки. Если левый операнд не является строкой или Symbol, он принуждается к строке. Это все полностью в спецификация:

JavaScript неизученные массивы - это объекты (и не массивы, хотя движки оптимизируют это, когда могут). Индексы массива являются именами свойств (и технически строками, хотя двигатели оптимизируют это, когда могут). Поэтому вы можете использовать in, чтобы проверить, содержит ли массив свойство с помощью "индекса массива" с in и массивом. (Вы также можете использовать hasOwnProperty: theArray.hasOwnProperty(0), но он медленнее с массивами на современных машинах.)

Что он должен делать:

Пусть q - массив с такими элементами:

[ 5, <1 empty slot>, undefined, 5 ]

Тогда:

  • 0 in q, 2 in q, 3 in q равно true;
  • 1 in q равен false.

Да, это совершенно верно:

var q = [];
q[0] = 5;
q[2] = undefined;
q[3] = 5;
for (var i = 0; i < q.length; ++i) {
  snippet.log(i + " in q? " + (i in q));
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>