Создание объектов в виде массива в JavaScript
В JavaScript есть объекты, которые притворяются массивами (или похожими на массивы). Такие объекты arguments
, NodeList
(возвращаются из getElementsByClassName
и т.д.) И объекты jQuery.
Когда console.log
ged, они отображаются как массивы, но это не так. Я знаю, что для того, чтобы быть массивным, объект должен иметь свойство length
.
Итак, я создал "объект" следующим образом:
function foo(){
this.length = 1;
this[0] = "bar";
}
var test = new foo;
Когда я console log(test)
, я получаю (как ожидалось) объект foo
. Я могу "преобразовать" его в массив с помощью
Array.prototype.slice.call(test)
Но я не хочу его преобразовывать, я хочу, чтобы он был подобен массиву. Как создать подобный массиву объект, так что когда он console.log
ged, он появляется как массив?
Я попытался установить foo.prototype = Array.prototype
, но console.log(new foo)
все еще показывает объект foo
, а не массив.
Ответы
Ответ 1
Зависит конкретно от консоли. Для пользовательских объектов в консоли разработчика Chrome и Firebug вам понадобятся свойства length
и splice
. splice
также должна быть функцией.
a = {
length: 0,
splice: function () {}
}
console.log(a); //[]
Важно отметить, однако, что официального стандарта нет.
Следующий код используется jQuery (v1.11.1) внутри, чтобы определить, должен ли объект использовать цикл for
или цикл for..in
:
function isArraylike( obj ) {
var length = obj.length,
type = jQuery.type( obj );
if ( type === "function" || jQuery.isWindow( obj ) ) {
return false;
}
if ( obj.nodeType === 1 && length ) {
return true;
}
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}
Обратите внимание, что возможно наличие объекта, который появляется в консоли как массив ([]
), но который перебирается с помощью цикла for..in
в jQuery или объекта, который отображается как объект в консоли ({}
), но он перебирается с помощью цикла for
в jQuery.
Ответ 2
Используется ли это: прототип расширенного массива, похоже, что он делает то, что вы делали, и создавая прототип в виде массива, но включая дополнительный метод (который может работать или не работать, я не тестировал это):
var MyArray = function() {
};
MyArray.prototype = new Array;
MyArray.prototype.forEach = function(action) {
for (var i = 0, l=this.length; i < l, ++i) {
action(this[i]);
}
};
Надеюсь, что это поможет.
Ответ 3
Я думаю, этот - это то, что вы ищете.
Переопределите функцию toString.
foo.prototype.toString = function()
{
return "[object Foo <" + this[0] +">]";
}
Ответ 4
Посмотрите на это:
var ArrayLike = (function () {
var result;
function ArrayLike(n) {
for (var idx = 0; idx < n; idx++) {
this[idx] = idx + 1;
}
// this.length = Array.prototype.length; THIS WILL NOT WORK !
}
// ArrayLike.prototype.splice = Array.prototype.splice; THIS WILL NOT WORK !
// THIS WILL WORK !
Object.defineProperty(ArrayLike.prototype, 'length', {
get: function() {
var count = 0, idx = 0;
while(this[idx]) {
count++;
idx++;
}
return count;
}
});
ArrayLike.prototype.splice = Array.prototype.splice;
ArrayLike.prototype.multiple = function () {
for (var idx = 0 ; idx < this.length ; idx++) {
if (result) {
result = result * this[idx];
} else {
result = this[idx];
}
}
return result;
};
return ArrayLike
})();
var al = new ArrayLike(5);
al.__proto__ = ArrayLike.prototype;
console.log(al.length, al.multiple(), al);
Это будет отображаться в Chrome: 5 120 [1, 2, 3, 4, 5]