How does `["length"]` work? - javascript

Today when I read undersocre, I found an interesting syntax ["length"]
For example:
"hello"["length"] //5
[1,2,3,4]["length"] //4
This works in Chrome, Firefox and even IE5!
Is this a native js method or does it run in a array way like [1,2,3]["1"] or something like that?

It's a standard property of Array: Array#length
The length property represents an unsigned, 32-bit integer that is always numerically greater than the highest index in the array.
Or a standard property of String: String#length
The length property represents the length of a string.
It is a different use of a property accessor.
[0, 1, 2].length
[0, 1, 2]['length']

Related

How length property of an array works in javascript?

In javascript is it possible to directly set length property of an array. For example I can shorten the array like this:
var arr = [1, 2, 3, 4];
arr.length = 2;
console.log(arr); // Array [ 1, 2 ]
// arr[2], arr[3] are deleted
I would expect the length to be read-only (e.g. as in java).
As I understand, array in javascript is also an object:
console.log(typeof [1, 2, 3]); // object
How the length property works under the hood?
Array.prototype.length is a writable property of array.
Adding description from Array#lengthMDN
You can set the length property to truncate an array at any time. When you extend an array by changing its length property, the number of actual elements does not increase; for example, if you set length to 3 when it is currently 2, the array still contains only 2 elements. Thus, the length property does not necessarily indicate the number of defined values in the array.
This can be used to shorten an array.
As I understand, array in javascript is also an object:
console.log(typeof [1, 2, 3]); // object
Check Why does typeof array with objects return "Object" and not "Array"?
Generally, the length property is determined based on the highest index in the array.
Reading the length
1) For a dense array, this means that the length corresponds strictly to the number of elements:
var fruits = ['orange', 'apple', 'banana']; //fruits is a dense array
fruits.length // prints 3, the real count of elements
fruits.push('mango');
fruits.length // prints 4, one element was added
var empty = [];
empty.length // prints 0, empty array
The dense array does not have empties and the number of items corresponds to highestIndex + 1. In [3, 5, 7, 8] the highest index is 3 of element 8, thus the array size is 3 + 1 = 4.
2) In a sparse array (which has empties), the number of elements does not correspond to length value, but still is determined by the highest index:
var animals = ['cat', 'dog', , 'monkey']; // animals is sparse
animals.length // prints 4, but real number of elements is 3
var words = ['hello'];
words[6] = 'welcome'; //the highest index is 6. words is sparse
words.length //prints 7, based on highest index
Modifying the length
1) Modifying the property leads to cut the elements (if the new value is smaller than the highest index):
var numbers = [1, 3, 5, 7, 8];
numbers.length = 3; // modify the array length
numbers // prints [1, 3, 5], elements 7 and 8 are removed
2) or creating a sparse array (if the new value is bigger than the highest index):
var osTypes = ['OS X', 'Linux', 'Windows'];
osTypes.length = 5; // creating a sparse array. Elements at indexes 3 and 4
// do not exist
osTypes // prints ['OS X', 'Linux', 'Windows', , , ]
Please read this post, which covers in details everything about the length of an array.
The necessary steps to be fulfilled when length is being set on an Array is described on section 9.4.2.4 ArraySetLength of ES 6.0 language specification.
It deletes index properties from the old length of the array to the new length of the array according to step 19:
While newLen < oldLen repeat,
Set oldLen to oldLen – 1.
Let deleteSucceeded be A.[[Delete]](ToString(oldLen)).
Assert: deleteSucceeded is not an abrupt completion.
If deleteSucceeded is false, then
Set newLenDesc.[[Value]] to oldLen + 1.
If newWritable is false, set newLenDesc.[[Writable]] to false.
Let succeeded be OrdinaryDefineOwnProperty(A, "length", newLenDesc).
Assert: succeeded is not an abrupt completion.
Return false.
Whenever you set up a property for the array, it checks first to see if the property is length and if it is, it's supposed to do the ArraySetLength operation. This operation is described in section 9.4.2.1 [[DefineOwnProperty]] (this for Array Exotic Objects).
When the [[DefineOwnProperty]] internal method of an Array exotic object A is called with property key P, and Property Descriptor Desc the following steps are taken:
Assert: IsPropertyKey(P) is true.
If P is "length", then
Return ArraySetLength(A, Desc).
If it's not length and it's an indexed property the other steps in the operation are performed. Basically sets the value of the length property to the value of the index property + 1. As far as I can tell, the ArraySetLength operation isn't being used here to set the new length of the array.
Is it possible ?
Yes, it's possibly to directly set length property of an array.
You could set length of array to be shorten or higher ( to create sparsed array) then existing array. That's the way you can achieve desired behaviour.
Information about that from First edition of EcmaScript Standart-262, 15.4 :
Specifically, whenever a property is added whose name is an array
index, the length property is changed, if necessary, to be one more
than the numeric value of that array index; and whenever the length
property is changed, every property whose name is an array index whose
value is not smaller than the new length is automatically deleted.
So when you assigned lower value of length than it was before for an array deleting items( they would be collected by garbage collector ECMA-262, 15.4.5.1) from that array.
How length determined ?
The length of an array is the highest index + 1. However you can update length of Array in both direction ( decrease to delete elements and increase to create sparsed Array).
How to create Array with defined length ?
To create Array with defined length, pass length value into Array constructor as in code below:
var length = 10;
var newArray = Array(length);
console.log(newArray.length);// 10
Use full links:
Mozzilla MDN Array
Delete JavaScript Array Elements
W3Schools JavaScript Array length Property
arr = arr.slice(0, 2); will give you the first 2 elements of the array as a new array.
I would say this method is much more clear than using array.length = number to set the length of an array.
From the specs :
Array objects give special treatment to a certain class of property
names.
...
whenever a property of an Array object is created or changed, other
properties are adjusted as necessary to maintain this invariant.
Basically since the built-in array methods like join, slice, indexOf, etc all get affected by the property change, it is also necessary to update the Array.
In this case, since length is changed, there will be a change to the keys in the array.
You may take a look to Paragraph 9.4.2: Array Exotic Objects, and subsequent paragraph "ArraySetLength" where is described the algorithm:
An Array object is an exotic object that gives special treatment to array index property keys (see 6.1.7). A
property whose property name is an array index is also called an element. Every Array object has a length
property whose value is always a nonnegative integer less than 2 32 . The value of the length property is
numerically greater than the name of every own property whose name is an array index; whenever an own
property of an Array object is created or changed, other properties are adjusted as necessary to maintain this
invariant. Specifically, whenever an own property is added whose name is an array index, the value of the
length property is changed, if necessary, to be one more than the numeric value of that array index; and
whenever the value of the length property is changed, every own property whose name is an array index
whose value is not smaller than the new length is deleted. This constraint applies only to own properties of an
Array object and is unaffected by length or array index properties that may be inherited from its prototypes.

What is the length property of the array x?

What would the length property of the array x be?
var x=new Array();
x[0]="Monday";
x[1]="Tuesday";
x[3]="Thursday";
It would be 4.
The .length property is defined to be one more than the numeric value of the largest integer-like property name. The largest (when interpreted as a number) such property name in the example code is 3, so the .length value is therefor 4.
If you set a property of an array, such that the property name is an integer (or a string that looks like an integer), then length is updated to be one more than that integer value. Symmetrically, if you set length to some value, then all properties whose names are integers greater than or equal to the new value are implicitly deleted.
if you want to know the length of your array 'x' then you can just do something like:
var length = x.length;
keep in mind that arrays are 0 based. So the length here will be 4, however, if you want to access the indexes of your array you will need to use 0, 1, 2, 3.
further, if you want to know the length, after getting your var length you could do either of the following:
console.log(length);
alert(length);

How does JavaScript [] really work?

I'm writing a JavaScript interpreter for extremely resource-constrained embedded devices (http://www.espruino.com), and every time I think I have implemented some bit of JavaScript correctly I realise I am wrong.
My question now is about []. How would you implement one of the most basic bits of JavaScript correctly?
I've looked through the JavaScript spec and maybe I haven't found the right bit, but I can't find a useful answer.
I had previously assumed that you effectively had two 'maps' - one for integers, and one for strings. And the array length was the value of the highest integer plus one. However this seems wrong, according to jsconsole on chrome:
var a = [];
a[5] = 42;
a["5"]; // 42
a.length; // 6
but also:
var a = [];
a["5"] = 42;
a[5]; // 42
a.length; // 6
So... great - everything is converted into a string, and the highest valued string that represents an integer is used (plus one) to get the length? Wrong.
var a = [];
a["05"] = 42;
a.length; // 0
"05" is a valid integer - even in Octal. So why does it not affect the length?
Do you have to convert the string to an integer, and then check that when converted back to a string, it matches?
Does anyone have a reference to the exact algorithm used to store and get items in an array or object? It seems like it should be very simple, but it looks like it actually isn't!
As the specs said, and was noted by others:
"A property name P (in the form of a String value) is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 2^32-1."
That's explain why in your scenario "5" is considered an array index and "05" is not:
console.log("5" === String("5" >>> 0));
// true, "5" is equal to "5", so it's an index
console.log("05" === String("05" >>> 0));
// false, "05" is not equal to "5", so it's not an index
Note: the Zero-fill right shift is the shortest way in JS to have a substitute of ToUint32, shifting a number by zero.
See MDN
It's possible to quote the JavaScript array indexes as well (e.g.,
years["2"] instead of years[2]), although it's not necessary. The 2 in
years[2] eventually gets coerced into a string by the JavaScript
engine, anyway, through an implicit toString conversion. It is for
this reason that "2" and "02" would refer to two different slots on
the years object and the following example logs true:
console.log(years["2"] != years["02"]);
So with a["5"] you are accessing the array while a["05"] sets a property on the array object.
Arrays are just objects. That means they can have additional properties which are not considered elements of the array.
If the square bracket argument is an integer, it uses it to perform an assignment to the array. Otherwise, it treats it as a string and stores it as a property on the array object.
Edit based on delnan's comment and DCoder's comment, this is how JavaScript determines if it is an appropriate index for an array (versus just a property):
http://www.ecma-international.org/ecma-262/5.1/#sec-15.4
Arrays are also objects.
By doing this
a["05"] = 5;
You are doing the same thing as:
a.05 = 5;
However, the above will result in a syntax error, as a property specified after a dot cannot start with a number.
So if you do this:
a = [];
a["05"] = 5;
you still have an empty array, but the property of a named 05 has the value 5.
The number x is an array index if and only if ToString(ToUint32(x)) is equal to x (so in case of "05" that requirement is not met).

Javascript Array with number as property name

var myArray = new Array();
myArray['112'] = 0;
myArray.length
Why is length 113 in above sample? Shouldn't '112' add a object property for the array and create something similar to myArray = {"112":0}?
Besides this, why is the length 113 and not 1? Since myArray actually only contains 1 value
The array length is one more than the highest index, so you get 113.
No. The '112' string and a pure numeric 112 evaluate to the same thing when JS is doing the array lookup, so you get a slot in the array rather than a property.
Simplest to think of a JS Array indexes as properties that happen to be numbers, even in string form. It's more chameleonic than you'd think at first.
But if you add a property with some nonnumeric name, like myArray['foo'], it will do as you expect and the length won't change.
Consider this simple example:
var aa = [];
aa[3] = 'three';
alert( aa.length // 4
+ '\n' + aa[2] // undefined
+ '\n' + aa.hasOwnProperty('2') // false
);
The number 3 is used to assign the property name, but it is converted to a string and used as a standard property name (i.e. the string "3").
Adding a property named "3" has created one property and set the length to 4 since the length is always set to one more than the largest non-negative integer property name.
No other property is created, the array is "sparse", i.e. it doesn't have sequentially named (numbered) members. A for..in loop can also be used to see that there is only one property.
You got array of 0..112 elements - in total length of 113 elements.

Does this create an array in JavaScript?

I am using the following JavaScript code:
var a = [23, 34, 45, 33];
Is a considered an array of integers?
Yes, a is an array. However, since Javascript isn't statically typed, it can contain other types as well, such as strings, objects, other arrays and so on. Therefore, tagging it as "an array of integers" wouldn't be right.
JavaScript doesn't have an Integer type. It is an Array containing Numbers (but not limited to containing only Numbers)
You are creating an array a using an array literal.
An array literal is a list of zero or more expressions, each of which represents an array element, enclosed in square brackets ([]). When you create an array using an array literal, it is initialized with the specified values as its elements, and its length is set to the number of arguments specified.
As the other answers already pointed out, JavaScript arrays are able to contain elements of different data types.
Yes, it is. It really is.
Interesting question...
a is considered an array of integers as long as you want it that way since javascript is dynamically typed, ie. you could potentially do:
var a = [23, 34, 45, 33];
alert(a[0] + 1); // shows 24
a = "sometext";
alert(a + 1); // shows "sometext1"
HTH.
Javascript supports var so you can have combination of string, int, decimal here.
To check further details see this link http://javascript.blogsome.com/category/1/javascript-array/

Categories

Resources