NodeJS: Array automatically gets converted into object? [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JavaScript: Check if object is array?
Why is an array of objects considered an object, and not an array? For example:
$.ajax({
url: 'http://api.twitter.com/1/statuses/user_timeline.json',
data: { screen_name: 'mick__romney'},
dataType: 'jsonp',
success: function(data) {
console.dir(data); //Array[20]
alert(typeof data); //Object
}
});​
Fiddle

One of the weird behaviour and spec in Javascript is the typeof Array is Object.
You can check if the variable is an array in couple of ways:
var isArr = data instanceof Array;
var isArr = Array.isArray(data);
But the most reliable way is:
isArr = Object.prototype.toString.call(data) == '[object Array]';
Since you tagged your question with jQuery, you can use jQuery isArray function:
var isArr = $.isArray(data);

Quoting the spec
15.4 Array Objects
Array objects give special treatment to a certain class of property names. 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. 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 property whose name is an array index; whenever a property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. 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. 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.
And here's a table for typeof
To add some background, there are two data types in JavaScript:
Primitive Data types - This includes null, undefined, string, boolean, number and object.
Derived data types/Special Objects - These include functions, arrays and regular expressions. And yes, these are all derived from "Object" in JavaScript.
An object in JavaScript is similar in structure to the associative array/dictionary seen in most object oriented languages - i.e., it has a set of key-value pairs.
An array can be considered to be an object with the following properties/keys:
Length - This can be 0 or above (non-negative).
The array indices. By this, I mean "0", "1", "2", etc are all properties of array object.
Hope this helped shed more light on why typeof Array returns an object. Cheers!

Try this example and you will understand also what is the difference between Associative Array and Object in JavaScript.
Associative Array
var a = new Array(1,2,3);
a['key'] = 'experiment';
Array.isArray(a);
returns true
Keep in mind that a.length will be undefined, because length is treated as a key, you should use Object.keys(a).length to get the length of an Associative Array.
Object
var a = {1:1, 2:2, 3:3,'key':'experiment'};
Array.isArray(a)
returns false
JSON returns an Object ... could return an Associative Array ... but it is not like that

Related

Array.length is a property not a method, but how .length is work like a method?

A method can get a value from an Array with the logic of that method. but length is not a method to an array, though returning a value when we write array.length, How?
"How did I get to know that .length is property to an array? is 'We all know that a method should have () when we are invoking a method, but .length don't invoke with (). so it is property to an object'".
var arr = [1,2,3,8,6,4,9,5,8,6];
console.log(arr.length); //10 -
console.log(Math.max(...arr)); //9
max() is returning a value because it is methode
As a property how does .length return a value?
Arrays are officially called "Array exotic objects". This sort of very weird behavior you're seeing, where an object property apparently changes itself automatically, is not visible (or possible to implement) on ordinary Javascript objects:
This specification defines several kinds of built-in exotic objects. These objects generally behave similar to ordinary objects except for a few specific situations. The following exotic objects use the ordinary object internal methods except where it is explicitly specified otherwise below:
and
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 232. 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.
In other words, an array's .length is a specific exception to the general rule that objects' properties do not change by themselves.
Note that getters can have a similar functionality:
const obj = {
get length() {
return Object.keys(this)
.filter(key => /^[0-9]+$/.test(key))
.length;
}
};
obj[0] = 'x';
obj[1] = 'y';
console.log(obj.length);
But an array's .length is not a getter, at least not visibly:
var arr = [1,2,3,8,6,4,9,5,8,6];
console.log(Object.getOwnPropertyDescriptor(arr, 'length'))
If it were a getter, you'd instead see a get property on the descriptor, like:
const obj = {
get length() {
return Object.keys(this)
.filter(key => /^[0-9]+$/.test(key))
.length;
}
};
console.log(Object.getOwnPropertyDescriptor(obj, 'length'))
Array length is all implemented under-the-hood, and not visible to the running Javascript.
You could take a property and assign or get a value from it, but it is iomplementes as setter and getter. This allows to use a function as simple property and uses the assigned value for changing other things, like to remove items.
var object = {
l: 42,
get length() { return this.l; },
set length(l) { this.l = l; },
}
console.log(object.length);
object.length = 2;
console.log(object.length);
Good Question. The only catch here is that you believe Array.length is calculated when you invoke/call this property. No, it does not happen like that.
When an Array is created, it's properties get set. These properties like length, prototypical functions etc. contain a value when an Array is created. When you execute Array.length, you are only getting the value of that property. In case of functions, the code execution happens when you invoke the call.
Think of it like a constructor in the Array definition which sets the property length as soon as an object of Array class is created and modified.
The length property of an object which is an instance of type Array
sets or returns the number of elements in that array. The value is an
unsigned, 32-bit integer that is always numerically greater than the
highest index in the array.
As stated, you can also use it to set the number of elements. This is achievable using a getter and setter by theory.
The following example sets the latest property of an object which will represent the last element of an internal array.
var obj = {
log: ['a', 'b', 'c'],
get latest() {
if (this.log.length == 0) {
return undefined;
}
return this.log[this.log.length - 1];
},
set latest(val) {
this.log[this.log.length - 1] = val;
}
}
obj.latest = 'z';
console.log(obj.latest);

why the type of a number element in an array is evaluated to be a string in javascript [duplicate]

This question already has answers here:
javascript for loop counter coming out as string [duplicate]
(3 answers)
Closed 3 years ago.
For example
var a = [1, 2, 3];
for (var i in a) {
console.log(typeof i);
}
Output
string
string
string
I am a Python programmer, and I find it very unintuitive. Why is not an element evaluated to be a number instead?
You are looping over the keys of the object. Meaning the keys you are actually testing is "0", "1", "2".
You can see that here, if you also console the i. Also, if you console the value that is located at that index in the array, and test that, you will see that it is a number:
var a = [1, 2, 3];
for (var i in a) {
console.log(i, typeof i, a[i], typeof a[i]);
}
In ES5, a new feature was added to arrays that loops through their values (and indexes): Array#forEach:
var a = [1, 2, 3];
a.forEach(function(v) {
console.log(v, typeof v);
});
In ES2015+, for-of was added, which will loop through the values using a for-style loop:
// ES2015+ only!!
let a = [1, 2, 3];
for (let v of a) {
console.log(v, typeof v);
}
why the type of a number element in an array is evaluated to be a string in javascript
If you really mean the element, not the index, then the problem is that you're just looking at the type of the wrong thing. See KevBot's answer.
If you're asking why the indexes (0, 1, and 2) are strings rather than numbers, since array indexes are normally numbers, it's because standard arrays in JavaScript aren't really arrays at all, they're just objects with some special behavior:
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 232. 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.
Until ES2015, all object property names were strings. (Now they can be either strings or Symbols.) Array indexes are just property names that conform to a specific definition:
A String property name P is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 232-1.
See also A myth of arrays (on my blog).

How to get the correct array length

In my code i initialize array then put a value inside it why the output be 0 ?in spite of this should be 1
var changedfields=[];
changedfields['product']="productname";
alert(changedfields.length);
You're creating an associative array (normal arrays have an numeric index) but are actually trying to build a HashMap (a key, value pair). Use Objects or ES6 Maps.
I hope the following example will help you out:
var changedfields = {}; // create an object
changedfields['product']="productname";
var keys = Object.keys(changedfields); // returns the keys of the object ['product']
alert(keys.length);
I would suggest to read more about datastructures in javascript and avoid associative arrays in general.
Length of a JavaScript object (that is, associative array)
associative array versus object in javascript
Your question is interesting. Following is the answer.
First of all Arrays in Javascript are object type.
The first line you wrote creates an empty array and it's type is object.
var changedfields=[];
The second line you wrote creates a property called product of changedfields and sets the value to productname. It allows you add the product property because Javascript Array type is object. If you just had var changedfields; you could not add this property.
changedfields['product']="productname";
The third line you wrote simply finds the length of the empty array.
alert(changedfields.length);
In Javascript associative arrays are achieved using object. But if you want to add the product name in changedfields array. You could use push method like below and check the length:
changedfields.push('productname');
console.log(changedfields.length);
Javascript numerical indexed array length
So the Javascript numerical indexed array length can be calculated this way:
console.log(array.length);
console.log(changedfields.length); // in your case
The Javascript associative array length
The Javascript associative array (object) length can be calculated following ways:
Option 1:
Object.len = function(obj) {
var objLen = 0;
for (i in obj) {
obj.hasOwnProperty(i) ? objLen++ : '';
}
return objLen;
};
console.log(Object.len(changedfields));
Option 2:
console.log(Object.keys(array).length);
console.log(Object.keys(changedfields).length); // in your case
Note: This has issues with Internet Explorer 8, Opera etc

Why doesn't the length of the array change when I add a new property?

var arr = ["Hello", "There", 123, 456, {
show: function (value) {
alert(value);
}
}];
arr[4].show(arr[0]);
arr["Hello"] = {
damn: function () {
alert("What's happening yo !");
}
}
arr.Hello.damn();
alert("Arr length is: " + arr.length);
Quoting ECMA Script 5 Specification of Array Objects,
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 232−1.
Since Hello is not valid, according to the above definition, it is not considered as an array index but just as an ordinary property.
Quoting MDN's Relationship between length and numerical properties section,
When setting a property on a JavaScript array when the property is a valid array index and that index is outside the current bounds of the array, the engine will update the array's length property accordingly
So, only if the property is a valid array index, the length property will be adjusted.
In your case, you have just created a new property Hello on the array object.
Note: Only the numerical properties will be used in all of the Array's prototype functions, like forEach, map, etc.
For example, the array shown in question, when used with forEach,
arr.forEach(function(currentItem, index) {
console.log(currentItem, index);
})
would print
Hello 0
There 1
123 2
456 3
{ show: [Function] } 4
even though the list of keys shows Hello.
console.log(Object.keys(arr));
// [ '0', '1', '2', '3', '4', 'Hello' ]
It is because, Array is derived from Object,
console.log(arr instanceof Object);
// true
and Hello is a valid key of the array object, but just not a valid array index. So, when you treat the array as an Object, Hello will be included in the keys, but the array specific functions will include only the numerical properties.
This happens because length is only updated when a new numeric property is added to the array as required by the specification:
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.
And an array index is specified to be:
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 232−1.
However, arrays are also objects - so you can add non-array-index properties to an array, just like you can add properties to any other JavaScript object (which is why your example doesn't throw either).
javascript length is calculated as 1+(highest numeric index element). so when you add arr['Hello'], you are only adding a string index which is not taken into account when calculating the array length.
This is the actual definition of the array length property as described in ECMAScript 5.1:
Every Array object has a length property whose value is always a
nonnegative integer less than 232. The value of the length property is
numerically greater than the name of every property whose name is an
array index; whenever a property of an Array object is created or
changed, other properties are adjusted as necessary to maintain this
invariant. 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. 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.
When you write:
arr["Hello"]=...
you are creating a new Object associated with the arr Array object, which does not affect the length of arr.
You can achieve the same effect by writing:
arr.Hello=...

Why does typeof array with objects return "object" and not "array"? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JavaScript: Check if object is array?
Why is an array of objects considered an object, and not an array? For example:
$.ajax({
url: 'http://api.twitter.com/1/statuses/user_timeline.json',
data: { screen_name: 'mick__romney'},
dataType: 'jsonp',
success: function(data) {
console.dir(data); //Array[20]
alert(typeof data); //Object
}
});​
Fiddle
One of the weird behaviour and spec in Javascript is the typeof Array is Object.
You can check if the variable is an array in couple of ways:
var isArr = data instanceof Array;
var isArr = Array.isArray(data);
But the most reliable way is:
isArr = Object.prototype.toString.call(data) == '[object Array]';
Since you tagged your question with jQuery, you can use jQuery isArray function:
var isArr = $.isArray(data);
Quoting the spec
15.4 Array Objects
Array objects give special treatment to a certain class of property names. 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. 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 property whose name is an array index; whenever a property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. 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. 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.
And here's a table for typeof
To add some background, there are two data types in JavaScript:
Primitive Data types - This includes null, undefined, string, boolean, number and object.
Derived data types/Special Objects - These include functions, arrays and regular expressions. And yes, these are all derived from "Object" in JavaScript.
An object in JavaScript is similar in structure to the associative array/dictionary seen in most object oriented languages - i.e., it has a set of key-value pairs.
An array can be considered to be an object with the following properties/keys:
Length - This can be 0 or above (non-negative).
The array indices. By this, I mean "0", "1", "2", etc are all properties of array object.
Hope this helped shed more light on why typeof Array returns an object. Cheers!
Try this example and you will understand also what is the difference between Associative Array and Object in JavaScript.
Associative Array
var a = new Array(1,2,3);
a['key'] = 'experiment';
Array.isArray(a);
returns true
Keep in mind that a.length will be undefined, because length is treated as a key, you should use Object.keys(a).length to get the length of an Associative Array.
Object
var a = {1:1, 2:2, 3:3,'key':'experiment'};
Array.isArray(a)
returns false
JSON returns an Object ... could return an Associative Array ... but it is not like that

Categories