In JavaScript, there are objects that pretend to be arrays (or are "array-like"). Such objects are arguments, NodeLists (returned from getElementsByClassName, etc.), and jQuery objects.
When console.logged, they appear as arrays, but they are not. I know that in order to be array-like, an object must have a length property.
So I made an "object" like this:
function foo(){
this.length = 1;
this[0] = "bar";
}
var test = new foo;
When I console log(test), I get (as expected) a foo object. I can "convert" it to an array using
Array.prototype.slice.call(test)
But, I don't want to convert it, I want it to be array-like. How do I make an array-like object, so that when it's console.logged, it appears as an array?
I tried setting foo.prototype = Array.prototype, but console.log(new foo) still shows a foo object, and not an array.
5 Answers 5
Depends specifically on the console. For custom objects in Chrome's developer console, and Firebug you'll need both the length and splice properties. splice will also have to be a function.
a = {
length: 0,
splice: function () {}
}
console.log(a); //[]
It's important to note, however, that there is no official standard.
The following code is used by jQuery (v1.11.1) internally to determine if an object should use a for loop or a for..in loop:
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;
}
Note that it's possible to have an object that appears in the console as an array ([]) but that gets iterated over with a for..in loop in jQuery, or an object that appears as an object in the console ({}) but that gets iterated over with a for loop in jQuery.
8 Comments
splice property did show it as an array!Array.arguments.splice set to undefined?console implementations. Afterall, there is no Array in ECMAscript (when we forget about TypedArrays).Object.prototype.toString.call(obj) === '[object Arguments]' in some browsers.The same question got into my mind as while we can use array like arguments parameter:
function arrayLike() {
console.log(typeof arguments)
console.log(arguments)
console.log(Array.from(arguments))
}
arrayLike(1,2,3)
So, let's try creating our own array-like object:
let arrayLikeObject = {
0: 1,
1: 2
}
console.log(Array.from(arrayLikeObject))
Obviously, there's no length property defined so our arrayLikeObject will only return an empty array. Now, let's try defining a length property:
let arrayLikeObject = {
length: 2,
0: 1,
1: 2
}
console.log(Array.from(arrayLikeObject))
What if length is set different?
let arrayLikeObject = {
length: 1,
0: 1,
1: 2
}
console.log(Array.from(arrayLikeObject))
// it will only return the value from first `0: 1`
let arrayLikeObject = {
length: 5,
0: 1,
1: 2
}
console.log(Array.from(arrayLikeObject))
// other 3 values will be printed as undefined
But, I don't want to convert it...
You actually wanted to create an array, not array-like object. The array-like object must be converted like you said:
Array.prototype.slice.call(arrayLikeObject)
// Or,
[].slice.call(arrayLikeObject)
If you do try to use array methods on array-like object, then you'll get type error:
let arrayLikeObject = {
length: 5,
0: 1,
1: 2
}
console.log(arrayLikeObject.sort())
Thus, to use the array methods on arrayLikeObject, we need to convert it into array as we did in preceding examples using Array.from.
Otherwise, you simply need to create an array:
let arr = [1,2] // I don't mean, you don't know
Other consideration:
You can't use it as constructor:
let arrayLikeObject = {
length: 1,
slice: function () {
return 1
}
}
console.log(new arrayLikeObject) // Type error
In the following snippet, the result will be [undefined] as the length property is set to 1 but there's no 0 indexed property:
let arrayLikeObject = {
length: 1,
slice: function () {
return 1
}
}
console.log(Array.from(arrayLikeObject))
But if you set the length to 0, then the result will be an empty array [] because we're telling that we don't have any values in this array-like object.
1 Comment
Is this any use: extended array prototype, seems like he's doing what you did and creating the prototype as an array, but including an extra method (that may or may not work, I've not tested this):
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]);
}
};
Hope it helps in some way.
Look at this :
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);
This will display in Chrome : 5 120 [1, 2, 3, 4, 5]
1 Comment
I think this is what you are looking for. Override the toString function.
foo.prototype.toString = function()
{
return "[object Foo <" + this[0] +">]";
}
1 Comment
console.log it, it displays like an array []. In Chrome, when you console.log(arguments) it's looks like an array, but it's really not.
argumentsworked. I wanted to know why they are logged as arrays. :-Pargumentsworks. It's how various consoles work, which may be different from each other. Perhaps I misinterpreted your sentence above a bit.