Сообщение от Белый шум
|
Так есть понятие или нету? А то я запутался
|
Если в спецификации говорится об индексах, то понятие определённо есть!
Сообщение от Aetae
|
Если вы шизофреник, то это ваши проблемы.
|
Сообщение от jaroslav.tavgen
|
а по сути скажу то, что наличие метода... подсказывало бы новичкам, что существует и метод lastIndexOf, наличие которого зачастую является сюрпризом.
|
Например, для меня было очевидно, что такие методы должны уметь работать и «вперёд» и «назад». Поэтому когда я узнал про
indexOf, то я практически сразу узнал про
lastIndexOf, когда задался вопросом, а как то же самое сделать с конца строки. (Тоже самое было с методами списка
reduce и
reduceRight и пр.)
Сообщение от jaroslav.tavgen
|
наличие метода firstIndexOf подсказывало бы новичкам, что существует и метод lastIndexOf
|
Совершенно не логично — оно скорей подсказывало бы, что если есть
firstIndexOf, то должен быть и
secondIndexOf и
thirdIndexOf и...
Сообщение от voraa
|
В javascript вообще нет такого понятия, как индекс массива.
|
Все объекты (включая и списки — экземпляры класса Array) в JS наследуют от класса Object, а значит они все похожи на экземпляры класса Object. Однако дальнейшее наследование позволяет описать более подробно структуры данных, а это значит, что у списков могут быть описаны индексы. (Согласно спецификации, объекты списка — это такие объекты, которые обеспечивают особую обработку определенному классу имён свойств — включая целочисленные индексы списка, числовое значение i которых находится в диапазоне +0 ≤ i < 2³² − 1.
https://tc39.es/ecma262/#sec-array-exotic-objects)
Т. е. вы можете обработать отдельно и собственные свойства списка как объекта и индексы списка.
var xs = [1,2,3];
xs["1.5"] = 15;
xs["-1"] = -1;
console.group("собственные свойства списка как объекта");
for(const [key, value] of Object.entries(xs)) {
console.log("свойство:", key, "значение:", value);
}
console.groupEnd();
console.group("индексы списка");
for(const [index, element] of xs.entries()) {
console.log("индекс:", index, "элемент:", element);
}
console.groupEnd();
var a = [];
a[15] = "⛵";
a[4371813261] = "⛴";
alert(a.length); // 16
Сообщение от voraa
|
Единственная экзотичность объекта Array связана с обработкой свойства length.
|
Ложь! Таких свойств — 4294967296. Свойство length, а также целочисленные индексы от 0 до 4294967294. Т. е. если вы возьмёте 4294967295 или большее целое число, то это число не будет являться индексом списка и не будет влиять на длину списка. См. пример выше.
Сообщение от voraa
|
Чем обычный объект не ассоциативный массив?
|
Это частный случай ассоциативного массива — когда ключами могут являться строки (числа приводятся к их строковому представлению) и символы. (а не любые типы данных)
Сообщение от laimas
|
А если углубляться и для различных языков, то "Чем обычный объект не ассоциативный массив?" в JS, это нечто приближенное, а в РНР именно ассоциативный массив.
|
В РНР — это только частично ассоциативный массив, т. е. его ключи ограничены типом строка, что означает, что он ничем не отличается от экземпляра класса Object в JS. (объект в JS мощней, поскольку ключами могут быть ещё и представители типа Symbol)
Ассоциативный массив — это такой тип данных — коллекция, состоящая из таких пар (ключ, значение) — что всевозможные ключи представлены в ней только один раз.
Смотрим в PHP, разные ключи 5 и "5" не могут быть представлены в так называемом «ассоциативном массиве», а значит — это не настоящий ассоциативный массив.
<?php
$a = [
5 => "Hi, guys!",
"5" => "Hi, y’all!"
];
echo json_encode([
length => count($a),
keys => array_keys($a),
elements => array_values($a)
], JSON_PRETTY_PRINT);
Запускаем...
Код:
|
~ via 🐘 v7.0.33
➜ curl "http://(:1):5000/aa.php"
{
"length": 1,
"keys": [
5
],
"elements": [
"Hi, y’all!"
]
}% |
Отличие в том, что в PHP неправильно названа структура типа «коллекция пар (строка, значение)», это явно не ассоциативный массив. Эта структура скорей соответствует тому, что было в ECMAScript 3 и называлось объектом. (но только, опять же, частично!)
Ассоциативный массив реализован, например, в C# —
Dictionary, Java —
HashMap, JavaScript —
Map.
Сообщение от voraa
|
А какое? Чем оно отличается от имени свойства?
Ну в С или каком другом языке это можно понять как номер элемента в последовательности, расположенной в памяти.
|
Сообщение от voraa
|
И получается, что массив ведет себя как голимый объектишко.
|
Так если сравнивать, то следует сравнивать подобные вещи! Например массив в C имеет конкретную длину, которая указывается при его инициализации, массив заполняется нулями, а затем вы можете указать конкретные элементы, как вы это делали тут в примере. (в JS это TypedArray)
var a = new Float64Array(4);
console.log(a); // массив заполнен нулями
// изменяем массив
a[0]=0; a[1]=1; a[3]=3;
console.log(a[2]); // 0, а вы ожидали что-то другое?
Сообщение от voraa
|
Прототип-то объект — у него нет индексов, а только свойства с именами. А наш массив зачем то вместо индекса лезет за свойством по его имени.
|
Экземпляры класса Array не используют никакую отдельную область памяти для хранения (как это делают типизированные массивы, см. пример выше), свойства, представленные целыми числами от 0 до 4294967294 включительно хранятся как и все остальные свойства объекта типа Array — именно как свойства, поэтому если вы напишете Array.prototype[2] = 2 или наоборот что-то не объявите, вы получите точно такой же результат, как если бы работали с экземпляром класса Object.
Однако именно свойства, представленные целыми числами от 0 до 4294967294 означают индексы списка, по которым можно получить соответствующие элементы списка. Все методы списка работают именно с индексами.
Рассмотрим ещё пару примеров с вашим списком...
var xs = [1,2,3];
xs["1.5"] = 15;
xs["-1"] = -1;
// элементы списка можно получить по индексам
alert(JSON.stringify(xs));
var a = new Array(4);
console.log(a); // список ничем не заполнен [empty × 4]
// изменяем список
a[0]=0; a[1]=1; a[3]=3;
console.log(a); // [0, 1, empty, 3]
// только для voraa, если вам нужен массив с предопределёнными
// значениями, то используйте наследование от класса Array
Array.prototype[2] = 2;
Array.prototype[20] = 20;
var a = new Array(4);
console.log(a); // список ничем не заполнен [empty × 4]
/*
Однако на самом деле теперь индексы 2 и 20 есть у всех массивов,
однако инициализируя массив при помощи [] или new Array(4),
свойство length определяется на самом списке (у каждого списка своя длина)
{
length: 4,
__proto__: {
"2": 2,
"20": 20,
length: 21,
constructor: Array,
// остальные методы и свойства
__proto__: {
constructor: Object,
// остальные методы и свойства объекта
__proto__: null
}
}
}
*/
// изменяем список
a[0]=0; a[1]=1; a[3]=3;
console.log(Array.from(a)); // [0, 1, 2, 3]
// Однако ручная инициализация приводит к тому,
// что видны все элементы
console.log(({ __proto__: Array.prototype }).map(v => v)); // [empty × 2, 2, empty × 17, 20]
// Ещё пример...
var b = { __proto__: Array.prototype };
b.push(22);
console.log(b); // [empty × 21, 22]
console.log(Array.from(b)); // [undefined × 2, 2, undefined × 17, 20, 22]
Списки так работают, поскольку они не используют отдельный объект для своих элементов, что компенсируется тем, что у списков есть множество методов, что позволяет исключить прямое манипулирование индексами.
Сообщение от jaroslav.tavgen
|
Почему такую штуку не ввели?
Array.prototype.last = function(){
return this[this.length-1];
}
|
Такой метод предполагает дополнительные проверки, получение последнего элемента, обёрнутого в контейнер (в данном случае список), позволяет почувствовать всю мощь монад! (Работает уже сегодня)
array.slice(-1).forEach(item => {
// do something with last item
});
Вытаскивание элемента из контейнера (в данном случае список) предполагает дополнительные проверки!
const item = array.last();
if(item) {
// do something with last item
});