Подтвердить что ты не робот

Как реализованы массивы javascript?

А именно, как выглядит следующий код:

var sup = new Array(5);
sup[0] = 'z3ero';
sup[1] = 'o3ne';
sup[4] = 'f3our';
document.write(sup.length + "<br />");

вывод '5' для длины, когда все, что вы сделали, задано различными элементами?

Моя проблема с этим кодом заключается в том, что я не понимаю, как изменяется length, не вызывая метод getLength() или setLength(). Когда я выполняю одно из следующих действий:

a.length
a['length']
a.length = 4
a['length'] = 5

в объекте, отличном от массива, он ведет себя как dict/ассоциативный массив. Когда я делаю это на объекте массива, он имеет особое значение. Какой механизм в JavaScript позволяет это сделать? Имеет ли javascript некоторую систему свойств, которая переводит

a.length
a['length']

в методы "get" и

a.length = 4
a['length'] = 5

в "установленные" методы?

4b9b3361

Ответ 1

Все в JavaScript - это объект. В случае Array свойство length возвращает размер внутренней области хранения для индексированных элементов массива. Некоторая путаница может вступить в игру, поскольку оператор [] работает как для числовых, так и для строковых аргументов. Для массива, если вы используете его с числовым индексом, он возвращает/устанавливает ожидаемый индексированный элемент. Если вы используете его со строкой, он возвращает/устанавливает именованное свойство в объекте массива - если строка не соответствует числовому значению, то он возвращает индексированный элемент. Это связано с тем, что индексы массива JavaScript привязаны к строкам неявным вызовом toString(). Честно говоря, это всего лишь одна из тех вещей, которые заставляют вас почесать голову и сказать "JavaScript, вот почему они смеются над вами".

Фактическое базовое представление может отличаться между браузерами (или это может быть не так). Я не полагался бы на что-либо иное, кроме интерфейса, который предоставляется при работе с ним.

Вы можете узнать больше о массивах Javascript в MDN.

Ответ 2

Важно знать, что когда вы делаете sup['look'] = 4;, вы не используете ассоциативный массив, а скорее изменяете свойства объекта sup. Это эквивалентно sup.look = 4;, поскольку вы можете динамически добавлять свойства объектов javascript в любое время. sup['length'] будет для экземпляра вывода 5 в вашем первом примере.

Ответ 3

Чтобы добавить к ответу tvanfosson: в ECMA-262 (спецификация 3.0, я считаю), массивы просто определяются как имеющие такое поведение для установки свойств (см. 15.4.5.1). Там нет общего механизма, лежащего в основе этого (по крайней мере, на данный момент) - это именно то, как оно определено, и как должны работать интерпретаторы javascript.

Ответ 4

Это действительно зависит от того, что вы собираетесь с ним делать.

[].length является "магическим".
Он фактически не возвращает количество элементов в массиве. Он возвращает наибольший инстастрированный индекс в массиве.

var testArr = [];  testArr[5000] = "something";  testArr.length; // 5000

Но метод, стоящий за установщиком, скрыт в самом движке.
Некоторые движки в некоторых браузерах предоставят вам доступ к их реализациям этих магических методов. Другие будут полностью заблокированы.

Поэтому не полагайтесь на методы defineGetter и defineSetter или даже на самом деле, методы __proto__, если вы не знаете, какие браузеры вы используете, а какие нет.

Это изменится в будущем, когда приложения с привилегиями, написанные в ECMAScript Next/6, будут иметь доступ к большему.

Браузеры, совместимые с ECMAScript 5, уже начинают предлагать магические методы get и set в объектах, и еще впереди...... но это, вероятно, некоторое время, прежде чем вы сможете сбросить поддержку oldIE и тонны смартфонов и т.д.

Ответ 5

Если вы намерены реализовать объекты с доступом к массиву, Array Mozilla dev center article - отличный ресурс. К сожалению, я не знаю подробных сведений о реализации Array, но в этой статье много деталей.

Ответ 7

Массив JavaScript - это объект, как и любой другой объект, но JavaScript дает ему специальный синтаксис.

arr[5] = "yo"

Вышеупомянутый синтаксический сахар для

arr.insert(5,"yo")

как вы добавляете материал к обычному объекту. Это то, что находится внутри метода insert, который изменяет значение arr.length

Посмотрите мою реализацию типа customArray здесь: http://jsfiddle.net/vfm3vkxy/4/

Ответ 8

Как уже упоминали другие люди, свойство в JavaScript может в основном выступать и как получатель, и как установщик вашего массива (или строки, или других входных данных).

На самом деле, вы можете попробовать это сами:

const test=[1,2,3,4,5]
test.length = 3
console.log(test) // [1,2,3]
test.length = 5
console.log(test) // guess what happens here!

Насколько я знаю, массивы в JS не работают точно так же, как ассоциативные массивы, и у вас есть элементы, которые помещаются в память максимально непрерывно (учитывая, что вы можете иметь массивы смешанных объектов), в зависимости от рассматриваемого вами механизма JS.

В качестве примечания, я немного озадачен тем, что ответ с наибольшим количеством голосов продолжает распространять чрезмерно упрощенный миф (или полуправду) о том, что "все является объектом в JavaScript"; это не совсем верно, иначе вы никогда не будете изучать примитивы, например.

Попробуйте сделать это:

const pippi = "pippi"
pippi.cat = "cat"
console.log(pippi.cat) // will it work? Throw an error? Guess why again

Спойлер: строка обернута в одноразовый объект для этой конкретной операции во второй строке, затем в следующей вы просто получите доступ к свойству примитива, которого там нет (при условии, что вы не играли с String.prototype или как), так что вы получите undefined.

Ответ 9

Характеристики массива Javascript

  1. Динамический - Массивы в Javascript могут динамически расти .push
  2. Может быть разреженным - например, для массива [50000] = 2;
  3. Может быть плотным - например, массив = [1, 2, 3, 4, 5]

В Javascript для среды выполнения сложно определить, будет ли массив плотным или разреженным. Так что все, что он может сделать, это сделать предположение. Все реализации используют эвристику, чтобы определить, является ли массив плотным или разреженным. Например, код в пункте 2 выше может указывать среде выполнения javascript, что это, скорее всего, реализация разреженного массива. Если массив инициализируется с начальным счетом, это может указывать на то, что это, вероятно, плотный массив.

Когда среда выполнения обнаруживает, что массив является разреженным, он реализуется аналогично объекту. Таким образом, вместо поддержания непрерывного массива строится карта ключ/значение.

Для получения дополнительной ссылки - https://www.quora.com/How-are-javascript-arrays-implemented-internally