Массив как объекты в Javascript - PullRequest
31 голосов
/ 06 июля 2011

Мне интересно, как jQuery конструирует свой массивоподобный объект.Главное, что я пытаюсь выяснить, - как ей удается заставить консоль интерпретировать ее как массив и отображать ее как таковую.Я знаю, что это как-то связано со свойством длины, но, немного поиграв, я не могу понять это.

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

Обычный объект, похожий на массив.

function foo(){
    // Array like objects have a length property and it's properties use integer
    // based sequential key names, e.g. 0,1,2,3,4,5,6 just like an array.
    this.length = 1;
    this[0] = 'hello'
}
// Just to make sure add the length property to the prototype to match the Array 
// prototype
foo.prototype.length = 0;

// Give the Array like object an Array method to test that it works     
foo.prototype.push = Array.prototype.push

// Create an Array like object 
var bar = new foo;

//test it 
bar.push('world');

console.log(bar);
// outputs 
{ 0: 'hello',
  1: 'world',
  length: 2,
  __proto__: foo
}

Где jQuery будет выводить

var jQArray = $('div')

console.log(jQArray);

// outputs
[<div></div>,<div></div>,<div></div>,<div></div>]

Если вы запустите

console.dir(jQArray)

// Outputs

{ 0: HTMLDivElement,
  1: HTMLDivElement,
  2: HTMLDivElement,
  3: HTMLDivElement,
  4: HTMLDivElement,
  context: HTMLDocument,
  length: 5,
  __proto__: Object[0]
 }

Прото объекта jQuery особенно интересен, поскольку его объект, а не jQuery.fn.init, как и следовало ожидать, также указывает на [0], поскольку это то, что вы получаетекогда ты.

console.dir([])
// outputs Array[0] as the object name or Array[x] x being the internal length of the
// Array

Я понятия не имею, как jQuery установил, что его прото-объект - Object [0], но я предполагаю, что ответ лежит где-то там.У кого-нибудь есть идеи?

Ответы [ 2 ]

44 голосов
/ 06 июля 2011

Объект должен иметь length и splice

> var x = {length:2, '0':'foo', '1':'bar', splice:function(){}}
> console.log(x);
['foo', 'bar']

и FYI, Object[0] в качестве прототипа по той же причине. Браузер видит сам прототип как массив, потому что:

$.prototype.length == 0;
$.prototype.splice == [].splice;
0 голосов
/ 06 июля 2011

Как это?

function foo() {
  this.push('hello');
}
foo.prototype = [];

var bar = new foo();
console.log(bar.length); // 1
console.log(bar); // ["hello"]
...