javascript — ключи массива и заполнение

#javascript #arrays

#javascript #массивы

Вопрос:

Я нахожу следующее поведение js немного странным и не могу понять, почему это происходит.

Предположим, что следующий код:

 var arrayName = new Array(15);
console.log(arrayName);
 

Это приведет к выводу [неопределенный, неопределенный, неопределенный, … ] (неопределенный 15 раз).

Теперь давайте используем следующий код:

 var arrayName = new Array(15).fill();
console.log(arrayName);
 

Поскольку для заполнения не было указано ни одного аргумента, это выведет (как и ожидалось) [неопределенный, неопределенный, неопределенный, … ] (неопределенный 15 раз).

Теперь давайте добавим цикл по массиву (используя формат for in, а не инкрементный):

 var arrayName = new Array(15);
console.log(arrayName);
for (var i in arrayName) {
    console.log(i);
}
 

Это ничего не выведет (не совсем то, чего я ожидал бы — я бы ожидал чисел от 0 до 14)

Теперь давайте использовать код с заполнением:

 var arrayName = new Array(15).fill();
console.log(arrayName);
for (var i in arrayName) {
    console.log(i);
}
 

Это приведет к 0, 1, 2, …, 14 ( чего я ожидал бы в обоих случаях).

Итак … в чем разница?

Я думаю, что индексы не создаются в первом случае (но все же выводятся неопределенные элементы … почему?). Является ли это несоответствием языка или за этим стоит какая-то логика?

PS Наведите курсор мыши на пустые поля, чтобы увидеть содержимое.

Комментарии:

1. это тест?????

2. Нет.. Я действительно не понимаю, почему это происходит. Если бы это был тест, я бы поставил его на codegolf :). Я добавил спойлеры, чтобы не влиять на мысли своим личным мнением. Это не реальный практический вопрос (я просто добавляю заполнение, когда мне это нужно), но я все равно хотел бы понять логику.

3. var arr = новый массив(15); console.log(arr); Это дает мне [] . Не то, что вы упомянули.

4. Записанный результат изменяется в зависимости от JS-движка браузера.

5. Ага… После комментария Netham я проверил в chrome и получил его результат. В ff это дает мое.

Ответ №1:

В принципе: НЕ ИСПОЛЬЗУЙТЕ FOR .ПЕРЕХОДИМ К МАССИВАМ! : http://ilikekillnerds.com/2015/02/stop-writing-slow-javascript /

for.in предназначен для объектов. Даже MDN заявляет об этом: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for…in

Массив создан и имеет некоторые индексы, но поскольку реальных данных (неопределенных) нет, то зачем нужны какие-либо ключи?

 //The difference is in enumerable keys:

console.log(Object.keys(new Array(15))); //Produces no keys since no data is allocated
console.log(Object.keys(new Array(15).fill())); //Produces 15 keys

//What you probably want is to loop through the allocated places in the array, not the keys of it:
for(var i = 0; i < new Array(15).length; i  ) {
  console.log(i)
} 

Почему это так?

Вы когда-нибудь пробовали Object.create ?

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

 //Allocating a new object
var test = Object.create({}, {
  p: {
    value: 42
  }
});

//Logging object... but where is p?
console.log("where is p?",test);

//there it is :)
console.log("there it is",test.p);

//Lets try that again
test = Object.create({}, {
  p: {
    value: 42,
    enumerable: true
  }
});

//Logging object... and there is p
console.log("All good",test);

//New object values are non-enumerable by default. Also on Arrays 

Комментарии:

1. Итак, вы говорите, что у вас может быть массив с длиной, но без ключей?

2. В принципе, да. Это то, что демонстрирует мой фрагмент, вызывая Object.keys массив. Когда вы запускаете for..in цикл, вы в основном выполняете стандартный for цикл, но с ключами, поэтому он не будет работать.

3. Да, я знаю, как это работает внутри (также знаю, каковы хорошие практики — и когда их игнорировать 🙂 — это был теоретический вопрос)… но я всегда думал, что свойство length строго связано с количеством существующих ключей. Тогда, по-видимому, является независимым.

4. Это связано с тем, как объекты создаются в JavaScript. Короче говоря, они не поддаются перечислению, если специально не указано иное. Если вы создаете массив из практически ничего, то индексы не будут перечислимы. Длина и ключи связаны, но ключи не обязательно можно перечислить.

5. ЭТО ответ, который я искал (я знаю, что я согласился раньше, но я сделал это, потому что я заполнил пробелы :)). Обычно я использую функцию генератора для объектов, которая по умолчанию делает атрибуты перечислимыми. Я не знал, что по умолчанию они не являются перечислимыми (и поскольку массивы в основном представляют собой подмножество объектов, не знал, что их ключи могут быть не перечислимы по умолчанию), отсюда и мое замешательство.

Ответ №2:

 var arrayName = new Array(15);
console.log(arrayName);
for (var i in arrayName) {
    console.log(i);
}
 

Давайте посмотрим, что произошло в приведенном выше случае.

 var arrayName = new Array(15);
 

Если единственным аргументом, переданным конструктору массива, является целое число
от 0 до 232 ^-1 (включительно), это возвращает новый массив JavaScript
с длиной, установленной на это число.

Итак, это то, что вы получили в приведенном выше случае. Итак, это пустой массив с длиной, равной 15. Теперь вы использовали цикл for in, который выполняет итерацию по перечислимому свойству, а переменной i на каждой итерации присваивается другое имя свойства

 console.log(arrayName.propertyIsEnumerable('length'));
 

Это возвращает false , поэтому имеющийся у вас массив не имеет свойства enumerable и является пустым массивом. Таким образом, вы ничего не получите.

Теперь во втором случае, поскольку вы использовали fill() , но не передали никакого значения в качестве первого аргумента, который используется для заполнения массива. Поскольку вы не передали никакого значения, весь массив был заполнен неопределенным, с индексами массива, определенными до длины массива. ( Смотрите конструктор для заполнения здесь https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/fill )

Также обратите внимание, что «Индексы массива — это просто перечислимые свойства с целочисленными именами».

Теперь цикл for в цикле повторил свойство индекса массива и напечатал их значение, которое выводит 0-14.

Для большего понимания, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for…in