В JavaScript, как мне получить доступ к объекту, унаследованному от Array, с помощью оператора []? - PullRequest
3 голосов
/ 21 июля 2010

У меня есть ситуация, когда мне нужно создать новый объект JavaScript, который унаследован от Array. Я использую следующий код:

// Create constructor function.
var SpecialArray = function () {};

// Create intermediate function to create closure upon Array's prototype.
// This prevents littering of native Array's prototype.
var ISpecialArray = function () {};
ISpecialArray.prototype = Array.prototype;
SpecialArray.prototype = new ISpecialArray();
SpecialArray.prototype.constructor = SpecialArray;


// Use Array's push() method to add two elements to the prototype itself.
SpecialArray.prototype.push('pushed proto 0', 'pushed proto 1');

// Use [] operator to add item to 4th position
SpecialArray.prototype[4] = 'direct [] proto to 4';

// Create new instance of Special Array
var x = new SpecialArray();

// Directly add items to this new instance.
x.push('pushed directly on X');
x[9] = 'direct [] to 9'

console.log(x, 'length: ' + x.length);

Интересно, что операция [] кажется бесполезной, и вывод консоли:

["pushed proto 0", "pushed proto 1", "pushed directly on X"] length: 3

Что мне здесь не хватает?

Ответы [ 3 ]

4 голосов
/ 21 июля 2010

Невозможно создать подкласс класса Array и использовать t таким образом.Лучшее решение для вас - расширить класс массива и использовать его как есть.Есть еще два варианта, которые мне не нравятся, но они существуют

3 голосов
/ 21 июля 2010

Это один из тех, кто всегда сбивает людей с толку.Свойство length применяется только к упорядоченным элементам.Вы не можете расширить массив, затем вставить произвольный несекретный ключ и ожидать, что он будет работать.Это потому, что связь между свойством length и содержимым массива нарушается после расширения массива.Приведенная выше ссылка Pointy очень хорошо объясняет это более подробно.

Чтобы доказать это, добавьте это в конец вашего примера:

console.log(x[4]);

Как видите, ваша запись присутствуети правильно, это просто не часть упорядоченного массива.

Как и все остальное в javascript, объект Array - это просто ассоциативный массив со строковыми ключами.Нечисловые, не последовательные ключи скрыты, чтобы обмануть вас, заставляя думать, что это «правильный» численно проиндексированный массив.

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

Как вы уже заметили, когда итерируете подобные структуры, не появляются несекретные ключи, что имеет смысл дляобщий случай использования массивов для упорядоченной информации.Это менее полезно или фактически бесполезно, когда вы хотите получить ключевую информацию.Я бы рискнул, если упорядочение неважно, вы должны использовать объект, а не массив.Если вам нужно как упорядоченное, так и неупорядоченное, сохраните массив как свойство объекта.

0 голосов
/ 11 июля 2016

Лучший способ, который я нашел для создания дочернего прототипа массива, - это не создание дочернего прототипа массива, а создание дочернего прототипа, подобного массиву. Существует множество прототипов, которые пытаются имитировать свойства «массива», но при этом все еще могут «наследовать» от него, лучший из найденных мной - Collection , потому что он сохраняет возможность использования скобки []. Основным недостатком является то, что он не очень хорошо работает с нецифровыми клавишами (т.е. myArray["foo"] = "bar"), но если вы используете только цифровые клавиши, он отлично работает.

Вы можете расширить этот прототип так:

http://codepen.io/dustinpoissant/pen/AXbjxm?editors=0011

var MySubArray = function(){
  Collection.apply(this, arguments);
  this.myCustomMethod = function(){
    console.log("The second item is "+this[1]);
  };
};
MySubArray.prototype = Object.create(Collection.prototype);

var msa = new MySubArray("Hello", "World");
msa[2] = "Third Item";
console.log(msa);
msa.myCustomMethod();
...