Array.length vs arrayinstance.length in javascript
functions have a .length
property which corresponds to how many arguments they are expecting. For example:
const unary = (a) => {
}
const binary = (a, b) => {
}
console.log(unary.length);
console.log(binary.length);
So the Array constructor has a length of 1 because it expects one parameter to be passed to it (namely, the size of the array).
array objects also have a .length
property, which is unrelated other than having the same name. This property says how large the array currently is.
I really think a lot of the other answers have covered everything needed here, but as it seems the OP hasn't had what they see a a clear answer, I will try to set everything out, somewhat extensively - but as clearly as I can - in order to clarify. (Apologies if anyone thinks I am "stealing" their answer - I assure you that this is not the intention, and I'm deliberately not looking at them as I type this, but I've certainly read most of them and even upvoted a few.)
Array.length
This has already been well-covered above. Array
is a native JS function, which you can use for creating arrays. It's less common then simply defining an array literal (and as far as I know there is no reason it would ever be preferable), but instead of var a = [1,2,3]
you are allowed to do this:
var a = Array(1,2,3);
console.log(a);
Note in passing that you don't want to do this to create a singleton array, there is an utterly mad gotcha of a special case when you supply exactly one parameter which happens to be an integer:
var a = Array(5);
console.log(a);
Although that shows what appears to be an array of 5 undefined
values in whatever JS console implementation SO uses, that's not actually quite what has been created (nor what is displayed in the current version of Chrome). I'm getting way off-topic but I'll refer you to Kyle Simpson's excellent walkthrough of the madness.
Anyway, since Array
is a function, as others have already observed, it has a length
property as all functions do. I'm really not sure why it evaluates to 1
though - for a user-defined function it is the number of arguments the function was formally declared with, but since Array
like all native JS functions isn't actually implemented in JS, I couldn't tell you how the implementation actually works. Clearly it can take any number of arguments and thus is a rather "exotic" function. I don't think that Array.length
would ever be useful, no matter what value was arbitrarily assigned to it, but it seems that most implementations go for 1, even if the specification leaves it open. (I'm not enough of a spec devotee to know if this is actually defined in there or left up to implementations.)
arrayinstance.length
This is just the feature of arrays that we know and use all the time. All JS arrays get this property - note that, although it is a property rather than a method (that is, it is not a function), it nevertheless "auto-updates" as the array gets longer/shorter:
var a = [1,2,3];
console.log(a.length);
a.push(4);
console.log(a.length);
a.pop();
a.pop();
console.log(a);
console.log(a.length);
Although as I said, Javascript's native constructors are not implemented in terms of JS itself, you could implement this kind of behaviour by defining a getter (at least since ES5).
Array.prototype.length
To fully explain what Array.prototype
(and similar objects) is would take me deep into how Javascript's object system work. Suffice to say here that, unlike class-based languages (and JS does not have classes, even in ES6, despite the class
syntax allowing us often to pretend it does), JS does not have the usual concept of "inheritance" that so-called OO languages do. In JS's version (sometimes called "prototypal inheritance"), what happens it that each object has an "internal prototype" which references some other object - and if you try to access a property on that object which it doesn't have, the JS engine will look at that "prototype object" for the property and use its value instead.
It's actually a very simple mechanism, but there are a number of things in the language which confuse this, one of them being the fact that functions (which are also objects) have a property called prototype
- which does not point to the real "prototype" object which gets consulted if a nonexistent property is referenced on the function object. (A normal function foo
has Function.prototype
is the object that it delegates to - not foo.prototype
.) However, if you declare a function foo
, an object called foo.prototype
is created - which is basically an empty, nondescript object. Its significance is that if the function foo
is used as a "constructor" - that is, if you make an object by calling new foo()
- foo.prototype
will then be the object that JS will look up properties (including methods) on if any object constructed from foo
happens to fail a property lookup.
This is why, at least in pre-ES6 code, you quite frequently saw this kind of pattern:
function foo(a,b) {
this.a = a;
this.b = b;
}
foo.prototype.add = function() {
this.a = this.a + this.b;
}
var myFoo = new foo(1,2);
console.log(myFoo.a);
myFoo.add();
console.log(myFoo.a);
myFoo.add();
console.log(myFoo.a);
console.log(myFoo.hasOwnProperty("add"));
Despite appearances, myFoo
doesn't actually have a method add
in this example - as confirmed by the final console.log
. When the JS engine fails to find the property though, it goes to myFoo
's "internal prototype", which happens to be foo.prototype
. And that's why the method works, as it would on any object constructed from foo
.
Anyway, this is leading up to the fact that Arrays, which could be (although almost never are) constructed by calling new Array
(I didn't use the new
operator above, but I could have done, this is a case where it makes no difference), therefore delegate to Array.prototype
. All those array methods that you know and love don't "really" exist on the arrays you call them on:
var a = [1,2,3];
a.push(4);
console.log(a);
console.log(a.hasOwnProperty("push"));
console.log(Array.prototype.hasOwnProperty("push"));
So array methods only work because those methods are actually found on the Array.prototype
object, to which all arrays delegate for property/method access if the lookup doesn't succeed on the array itself. (And this is why, if you look up any of them on MDN, the top of the page always says Array.prototype.<method_name>
, because that's where the method "really" lives.)
A drastic demonstration of this (please DON'T do this in production code!)
// you're used to doing this, and it works:
[1,2].push(3);
console.log("that went fine");
// vandalism on a grand scale!
Array.prototype.push = undefined;
// now you can'tse the "push" method anymore!
[1,2,3].push(4);
But I'm going to end on something of an anticlimax. The above is true for array methods - but the length
array property isn't a method. As observed above, it's just a "plain" (non-function) property, which "magically" behaves somewhat like a function call. As observed in the OP, .length
property accesses don't delegate as the method calls shown above do, the property exists on each array in itself.
So why does Array.prototype
still itself have a length
property? Well, Array.prototype
is actually itself an array. In fact, that's not the only thing:
Array.prototype.push(1);
console.log(Array.prototype);
Function.prototype();
notice that Array.prototype.push(1)
ends up with Array.prototype
being the singleton array [1]
. So Array.prototype
is "kind of like" the empty array (it's not exactly the same, because it has all those methods mentioned above directly accessible on the object itself, which a "normal" empty array doesn't). And with Function.prototype
, although calling it didn't output anything, the fact that no TypeError
was raised proves that it really is a function (it's actually a "no-op" function, like function() {}
, but once again with various methods diretcly on it - the methods which every function has access to, such as .call
and .bind
).
Anyway, to cut the digression short, since Array.prototype
is - as far as ordinary array properties are concerned, at least - an empty array, this explains why it has a length
property, and why it's equal to 0.
I hope this clears things up, as well as demonstrating some of the more intriguing parts of Javascript.