#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