Должны ли отрицательные индексы в массивах JavaScript способствовать длине массива?



в javascript я определяю такой массив



var arr = [1,2,3];


также я могу сделать



arr[-1] = 4;


теперь, если я делаю



arr = undefined;


Я также теряю ссылку на значение в arr[-1].



поэтому для меня логически кажется, что arr[-1] также является частью arr.



но когда я делаю следующее (без установки arr в undefined)



arr.length;


возвращает 3 не 4;



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

557   7  

7 ответов:

поэтому для меня логически кажется, что arr[-1] также является частью arr.

да, но не так, как вы думаете.

вы можете назначить произвольные свойства массиву (как и любой другой объект в JavaScript), что вы и делаете, когда вы "индексируете" массив в -1 и присвоить значение. Поскольку это не член массива, а просто произвольное свойство, вы не должны ожидать length учитывать, что свойство.

другими словами, следующий код делает то же самое:

​var arr = [1, 2, 3];

​arr.cookies = 4;

alert(arr.length);

The length свойство вернет номер один выше, чем самый высокий назначенный "индекс", где массив "индексы" являются целыми числами, большими или равными нулю. Обратите внимание, что JS позволяет" разреженные " массивы:

var someArray = [];
someArray[10] = "whatever";
console.log(someArray.length); // "11"

конечно, если нет элементов, то length и 0. Обратите внимание также, что length не обновляется, если вы используете delete удалить наибольший элемент.

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

someArray[-1] = "A property";
someArray[3.1415] = "Vaguely Pi";
someArray["test"] = "Whatever";

обратите внимание, что за кулисами JS преобразует имена свойств в строки, даже если вы указываете число, например -1. (Положительные целочисленные индексы также становятся строками, если на то пошло.)

методы массива, например .pop(),.slice() и т. д., работают только с нулевыми или более высокими целыми "индексами", а не с другими свойствами, поэтому length является последовательным в этом вопросе.

обратите внимание, что при использовании индекса позиции (или 0) значения помещаются в массив:

var array = [];

array[0] = "Foo";
array[1] = "Bar";

// Result: ["Foo", "Bar"]
// Length: 2

это не тот случай, когда вы добавляете неиндексные значения (не 0-9+):

var array = [];

array[0]  = "Foo";
array[1]  = "Bar";
array[-1] = "Fizzbuzz"; // Not a proper array index - kill it

// Result: ["Foo", "Bar"]
// Length: 2

значения помещаются в массив только тогда, когда вы играете по правилам. Когда вы этого не делаете, они не принимаются. Однако они принимаются на самом объекте массива, что имеет место практически со всем в JavaScript. Даже если ["Foo", "Bar"] единственные ценности в наше время, мы все еще можем доступ "Fizzbuzz":

array[-1]; // "Fizzbuzz"

но обратите внимание еще раз, что это не является частью значений массива, так как его "индекс" не является допустимым. Вместо этого он был добавлен в массив как еще один член. Мы могли бы получить доступ к другим членам массива таким же образом:

array["pop"]; // function pop() { [native code] }

обратите внимание, что мы обращаемся к pop метод на массиве, который сообщает нам, что это содержит собственный код. Мы не обращаемся ни к одному из значений массива с ключом "pop", а скорее к члену объекта массива себя. Мы можем дополнительно подтвердить это, проехав на велосипеде по публичным членам объекта:

for (var prop in array) 
    console.log(prop, array[prop]);

, который выплевывает следующее:

 0 Foo
 1 Bar
-1 Fizzbuzz

так опять же, это on the объект, но не на the массив.

удивительный вопрос! Заставил меня сделать два точно.

Если вы действительно хотите, чтобы отрицательные индексы и другие индексы были включены в длину, то создайте функциональность самостоятельно:

function getExtendedArray() {
    var a = [];

    Object.defineProperty(a, 'totalLength', { 
        get : function() { return Object.keys(a).length; }
    });

    return a;
}

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

var myArray = getExtendedArray();
console.log(myArray.totalLength); // 0
myArray.push("asdf");
myArray[-2] = "some string";
myArray[1.7777] = "other string";
console.log(myArray.totalLength); // 3

массивы в JavaScript на самом деле являются объектами. Они просто прототип из конструктора массива.

индексы массива на самом деле являются ключами в хэш-карте, и все ключи преобразуются в строки. Вы можете создать любой ключ (т. е. "-1"), но методы на массиве адаптированы, чтобы действовать как массив. Так что length Это не размер объекта, это скорее только гарантированно будет больше, чем самый большой целочисленный индекс. Аналогично, печать arr будет только список значений с целочисленными ключами >= 0.

подробнее здесь.

согласно MDN:

значение свойства length является целым числом с положительным знаком и значением меньше 2 в 32 степени (232)

в Javascript можно задать свойство для любого создаваемого объекта.

var array = new Array();
array = [1,2,3];
array["boom"] = "pow";

точно так же, когда вы устанавливаете отрицательный индекс, он сохраняет его как свойство в массиве, а не часть индекса.

array[-1] = "property does not add to array length";

вот почему длина не отражает его, но a for..in петля показывает оно.

при использовании неположительных или нечисловых индексов массив ведет себя как ассоциативный массив, который имеет пары ключ-значение.

для перебора массива можно использовать

for(var index in myArray) {
  document.write( index + " : " + myArray[index] + "<br />");
}

Comments

    Ничего не найдено.