I have following array:
var arr = [];
console.log(arr.length); //Output: 0
arr["1231321"] = "abcd";
console.log(arr.length); //Output: 1231322
arr["1231321".toString()] = "abcd";
console.log(arr.length); //Output: 1231322
arr["a1231321"] = "abcd";
console.log(arr.length); //Output: 0
arr["1231321a"] = "abcd";
console.log(arr.length); //Output: 0
Here is the Fiddle: http://jsfiddle.net/HcrcR/
when I change my arr to var arr = {}; then it works.
but what is the reason of it even if I use string key it starts pushing the data from key?
I have following array/hashmap:
That's an Array in JavaScript terms.
var arr = [];
console.log(arr.length); //Output: 0
That's expected, it's an empty array.
arr["1231321"] = "abcd";
console.log(arr.length); //Output: 1231322
The reason the length property is so large as it's always +1 than the highest index. It doesn't matter that you used a string, keys for Arrays and Objects are always strings in JavaScript.
The length property of this Array object is a data property whose value is always numerically greater than the name of every deletable property whose name is an array index.
Source
arr["1231321".toString()] = "abcd";
console.log(arr.length); //Output: 1231322
Calling toString() on a string doesn't do anything (it's already a string).
arr["a1231321"] = "abcd";
console.log(arr.length); //Output: 0
Also expected, you set a property on the Array which doesn't look like an index.
arr["1231321a"] = "abcd";
console.log(arr.length); //Output: 0
See above. There is no parsing internally of the string to try and get a number.
when I change my arr to var arr = {}; then it works.
That's how objects work in JavaScript. They're just a bucket of string keys to values.
Array != Object (or hashmap) in JavaScript. Therefore, properties added to an array that aren't integer indexes don't affect Array.length
Note that there is not reserving of space, just because the length is 1231321, it doesn't mean that all the spaces are allocated, JavaScript arrays don't have to use contiguous memory, and often don't if they are sparse. In reality, they are only contiguous as an optimization, and the default behavior is that they are hash maps just like objects.
If you need to know all the keys that an object has, you need to use https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys
However, you should not mix both concepts, in JS, you should either be working with an array (numeric indexes) or an object (any indexes)
When you do
arr["1231321"] = "abcd";
That's the same as
arr[1231321] = "abcd";
Which affects the length of the array. However,
arr["1231321a"] = "abcd"
Does not create a new array index (just a new object property) and it doesn't affect the length property
Note that your example in your question is incorrect, if you type the following commands one after the other
arr = [];
arr["1231321"] = "abcd";
console.log(arr.length); //Output: 1231322
arr["a1231321"] = "abcd";
// Output: 1231322, should be the same as before, not undefined
console.log(arr.length); //Output: 1231322
http://jsfiddle.net/tWCa4/
It is able to use your first 2 strings as indices, since they are able to be parsed as numbers.
When you pass it something that can't be parsed as an integer, the array will instead attach that as a property of the array, rather than an entry.
When you define it as an object, it will act as an object and treat everything as a string property. Length will always be defined as the highest value+1 for an array in javascript.
So to be clear
var x = []
creates a new Array which will try to parse its inputs to integers and add them into the array, but will otherwise assign them as properties.
var x = {}
will create an Object, which works as an unordered set of properties and will not have a length unless you custom define x.length = y in which case it will simply be another property with no special meaning.
Related
Why negative indexing of an array in JS doesn't raise an error? It looks like it not intended to have elements with a negative index in an array:
array.length doesn't count elements with negative indices.
array.forEach() doesn't iterate over elements with negative indices.
UPD. The question is not "why it is thechnically possible" buth rather "why it is allowed by design".
[RESOLVED] Short answer: there is no particular reason, it just happened to become like this.
Arrays are the special type of object in JavaScript. It has an extra list of methods and properties (like .length and .forEach), and also it has a list of used indexes (integer positive number starting from zero higher).
But just like any other object, it can have additional properties:
var arr = ['A', 'B'];
arr.extra = 'C';
console.log(arr[0], arr[1], arr.extra); // A B C
Because of object properties can be accessed not only via dot but also via square brackets you can access any property using array-like syntax:
var obj = { extra: 'D' };
console.log(obj['extra']); // D
console.log(arr['extra']); // C
Using the same syntax you can assign properties:
obj['x'] = 'E';
obj[33] = 'F';
arr['y'] = 'G';
arr[-1] = 'H';
console.log(obj.x, obj[33], arr.y, arr[-1]); // E F G H
You can safely use numbers as a property name for the object, it will automatically be converted to a string.
The only difference is when you use positive integer values for the name of the property. Those are interpreted as array indexes.
var arr = [];
arr[0] = 'A';
arr[1] = 'B';
arr[-1] = 'C';
arr.forEach(value => console.log(value)) // A, B
console.log(arr.length); // 2
console.log( Object.keys(arr) ); // ["0", "1", "-1"]
Arrays in javascript also can work as hash objects (as almost all objects in js including functions). So doing: a[-1] = -1 simply defines a new key in the array (as object hash) with key value "-1" and value -1.
You should know that almost all objects in javascript can be used as hash objects as well. This is what you see. However these keys (which are not positive integers) for arrays do not count as array keys in the normal sense, only as hash keys.
JS allows negative indices in an array for the simple reason that they are objects under the hood. You can also put [].blah = 5 and it would be valid but a terrible idea.
I'm trying to understand why Javascript prints an empty array when it should have at least one value inside it. Please, check this code:
detail = [];
detail.cat1=[];
detail.cat2=[];
detail.cat3=[];
detail.cat4=[];
var newEntry = {"cod":"01","dt":"2021-10-02 09:07:21.205-07:00"};
detail.cat2.push(newEntry);
console.log(detail);
console.log(detail.length);
console.log(detail.cat2);
The results are:
> Array []
> 0
> Array [Object { cod: "01", dt: "2021-10-02 09:07:21.205-07:00" }]
How could it print [] since I have one object inside? And how can the length be zero? I was using any Javascript online editor, and the result is the same.
Since an array is really an object, we can add methods/properties directly to an individual array.
Then if you want to see the keys in an object for instance, Object.keys won't see it, but Reflect.ownKeys() will.
The Reflect version of defineProperty will return success or fail, while Object's returns the object passed.
Remember Reflect.preventExtensions() will (like it says) stop you or others from extending them.
As far as question about length is there, ".length" gives length of values not properties so it still gives 0
Array is an indexed collection of values, means you can put element at particular index and get element from particular index.
In the below example, you can see that if there are already elements in an array then you can get its length using length property.
Remember: The length of an array is (highest integer index at which the element is present in array + 1)
const arr = [1, 2, 3, 4];
console.log(arr); // prints whole array
console.log(arr.length); // prints length of an array
console.log(arr[2]); // Element at index 2
If you set element at particular index let say arr[8] = "something" then its length will be 9
const arr = [];
arr[8] = "something";
console.log(arr.length) // 9
It is true that array's are objects, so you can set/get values to/from array. But if you set property that is not a numbered index then it will not increase its length but It will set the property to that array object as:
const arr = [];
arr["introduction"] = "I'm an array";
arr.property = "This is a property"
console.log(arr.length);
console.log(arr.introduction);
console.log(arr.property);
When displaying an array, the default Array.prototype.toString method is usually called. This actually calls Array.prototype.join with no arguments, so produces a comma separated string of the elements of the array.
The join method only returns properties that have a positive integer name (an array index, indicating an array element), other properties are ignored by join.
Similarly, only elements of the array affect the length property, ordinarly properties (i.e. those that don't have an array index for their name) don't affect length.
This is my JavaScript array code for negative index number.
In output why doesn't consider negative index number in the count of the element? It shows only count (3) in output.
Code
let abc = ['gnagar', 'ahmedabad', 25];
console.log(abc, typeof(abc));
console.log(abc[-1]);
abc[-1] = 'abc';
console.log(abc, typeof(abc));
console.log(abc[-1]);
-1 is not a valid index for array.
The assignment abc[-1] = 'abc'; means set attribute "-1" to the abc object.
This is because array is type of object as you can see there typeof(abc) is object.
You can assign values in objects using [].
Negative indexes are not actual index so it does not impact the array length.
See below given scenario
var x = [];
x['abc'] = "hello";
console.log(x.length); //returns 0
var x = [1,2];
x['abc'] = "hello";
console.log(x.length); //returns 2
Any reason behind this or Am i missing anything?
As per spec
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.
Further
Specifically, whenever an own property is added whose name is an array
index, the value of the length property is changed.
So, length property is adjusted when the property whose name is an array index is created, only then length property changes.
'abc' being a non-numeric (and hence not an index of an array) when added to the array, doesn't reflect any change in length property.
By writing
var x = [ ];
you are defining a standard array where indexes can only be integers.
x['abc'] = "hello";
When you do x["abc"] since abc (which is what you use as index) is not an integer you are basically defining a property to the arr object (everything is object in javascript) but you are not adding an element to the standard array. and hence you array remains as it was.
var x = [];
x["abc"] = "hello";
console.log(x);
and that is the reason the size of the array is 0 in the first case and 2 in the second
When you wish to add property to x with string keys, you need to define you variable as an object.
var x = {}
x['abc'] = "hello";
and then you can get the size of you Object(which is indeed the number of keys in your object) by
Object.keys(x).length
you cannot access the array without the index. If you want to insert particular data in an array you can give it like,
var x = [];
x[0] = "hello";
alert(x.length) //will return 1
What you have done is that you have converted your array into an associative array, where your indices are the reference to the value assigned. This is similar to the objects concept in Javascript.
The length is 0 because a real array starts from index 0. So if you check for your array
console.log(x[0]) //undefined
hence, the length 0.
You cannot append a user defined key that isn't a number in JavaScript, as you can do in Python or Php etc. In JavaScript the key's of the Array shall only be numeric.
Thus doing:
var x = [];
x['abc'] = "hello";
console.log(x.length);
returns the length of x as 0. As nothing has been pushed into the array.If you do console.log(x), you'll find out that the array has no values or is empty.
Whereas doing this:
var x = [1, 2];
x['abc'] = "hello";
console.log(x.length); //returns 2
returns the length as 0 because the array consists of number 1 at the index 0 and the number 2 at the index/position 1 of that array. Just those values are there in the array, if you want to push "hello" push it like, x.push("hello") which will push it at the index 2 of the array.
If you still want to use alphabetic index use Objects instead.
Could someone explain this (strange) behavior? Why is the length in the first example 3 and not 2, and most importantly, why is the length in the second example 0? As long as the keys are numerical, length works. When they are not, length is 0. How can I get the correct length from the second example? Thank you.
a = [];
a["1"] = {"string1":"string","string2":"string"};
a["2"] = {"string1":"string","string2":"string"};
alert(a.length); // returns 3
b = [];
b["key1"] = {"string1":"string","string2":"string"};
b["key2"] = {"string1":"string","string2":"string"};
alert(b.length); // returns 0
One thing to note is that there is a difference between regular arrays and associative arrays. In regular arrays (real arrays), the index has to be an integer. On the other hand, associative arrays can use strings as an index. You can think of associative arrays as a map if you like. Now, also note, true arrays always start from zero. Thus in your example, you created an array in the following manner:
a = [];
a["1"] = {"string1":"string","string2":"string"};
a["2"] = {"string1":"string","string2":"string"}
Javascript was able to convert your string indexes into numbers, hence, your code above becomes:
a = [];
a[1] = {"blah"};
a[2] = {"blah"};
But remember what i said earlier: True arrays start from zero. Therefore, the javascript interpreter automatically assigned a[0] to the undefined. Try it out in either firebug or the chrome/safari console, and you will see something like this when you try to print "a". You should get something like "[undefined, Object, Object]. Hence the size 3 not 2 as you expected.
In your second example, i am pretty sure you are trying to simulate the use of an associated array, which essentially is adding properties to an object. Remember associated arrays enable you to use strings as a key. So in other terms, you are adding a property to the object. So in your example:
b["key1"] = {"string1":"string","string2":"string"};
this really means:
b.key1 = {"string1":"string","string2":"string"};
Initializing b =[] simply creates an array, but your assignment doesn't populate the array. It simply gives "b" extra properties.
length returns 1 + the largest integer key in the object.
In a the largest key is 2 so 1+2 is 3.
In b there are no integer keys (the keys there are key1 and key2 which cannot be converted into ints) so Javascript assumes that the largest key is -1, and 1 + -1 yields 0.
This program will help you see that:
a = [];
a["1"] = {};
a["4"] = {};
alert(a.length); // Prints 5
From the ECMAScript standard, ECMA-262, 5th ed.
15.4.5.2 length
The length property of this Array object is a data property whose value is always numerically greater than the name of every deletable property whose name is an array index.
Note the length property of an array only takes into account array indices, which are integers; setting other properties doesn't affect length.
For an array, a["3"] is equivalent to a[3] (this behavior is specified by ยง 15.4.5.1); 3 is an array index rather than a property. Thus setting a["3"] affects the array's length. b["key1"] is equivalent to b.key1. Setting properties don't affect the length of a collection.