What does [literal] in [array/object] mean? - javascript

What does the following syntax mean:
1 in [1,2,3,5]
I know it doesn't search for 1 in the array. But what does it do?
I've seen it used in loops:
for (var i in testArray)
{
}
But have also seen this used by itself. Does it mean check if the literal is a valid index in the array or object that is the other operand?

Very simply, it's an object property search:
print ('a' in {'a':1, 'b': 2}); // true
print ('c' in {'a':1, 'b': 2}); // false
Live demo.
This is subtly different to the similar use of in in for loops.
Also note that it should not be used with arrays, although this is a common error to make.
It is unspecified what properties besides numeric keys make up the internals of an array, so you should stick to the Array API (e.g. indexOf) if you're using Arrays, otherwise you'll end up with behaviour that you may not expect:
print ('length' in [1,2,3,4]); // true

literalinobject means: "Get a property literal from object."
When used in a loop, the engine will try to access all properties of the object.
1 in [1,2,3,4] doesn't check for an occurence of an element with a value of 1, but it checks whether element 1 (array[1]) exists or not.

It looks like a cheap way not to use a traditional for loop for each item in the array.
Your 2nd example is a for-each loop. It doesn't have the literal 1 (one).

It's used to iterate JavaScript objects.
This loop will iterate through each "key" in the object.
Its common usage is iterate through such objects:
var Car = { color: "blue", price: 20000 };
for (var key in Car)
console.log("Propery " + key + " of Car is: " + Car[key]);
Live test case - check Chrome/Firefox JavaScript console to see the output.
When used for plain arrays, each "key" will be the index.. for example:
var nums = [20, 15, 30]
for (var key in nums)
console.log("Propery " + key + " of array is: " + nums[key]);
Will show the keys as 0, 1 and 2. Updated fiddle for such case.

'in' operator returns true if specified property exists in specified object; used in a loop it allows you to iterate over all properties of the object

Related

Forcing string representation of an array key

I am trying to maintain the order of an array with mixed key types. The array contains mostly keys represented by string values -- but if you enter a numbered key it goes to the front. How can I force a key which is a number to be a string type?
E.g.
array = [];
array["one"] = "some data";
array["two"] = "some more data";
array["3"] = "this should not be the first element";
How can I make "3" a string type to prevent it from moving to the top of the index?
Oh wow did you ever open multiple cans of worms.
Javascript arrays are a special type of Javascript objects, and like all Javascript objects they can have arbitrary string properties:
const foo = [];
foo["bar"] = "hi";
However that string is a property of the array object, not an item in the array:
foo.forEach(console.log); // logs nothing
You can still access it like any other object property:
console.log(foo["bar"]); // "hi"
But it won't show up in the usual iterative constructs like c-style for loops or the map/forEach array methods.
The line in your example
array["3"] = "this should not be the first element";
is very different however, because of Javascript's playing fast and loose with type conversions this actually sets the string to the 4th slot in the array:
const bar = [];
bar["3"] = "oops!"; // equivalent to bar[3] = "oops!"
console.log(bar); // [empty x 3, "oops!"]
This piece of it is actually a good thing (other than the implicit conversion part) rather than a problem: sometimes you need a sparse array and JS supports those. Iterating it will only produce the one element:
bar.forEach((item, index) => console.log(item, index)); // ["oops", 3]
Note though that the string has the correct index of 3, and can be accessed that way even though there's nothing "in front" of it:
bar[3]; // "oops"
So the first two assignments in your example create properties on the array object, and the third assignment is the only one that actually adds an item to the array, at the 4th index (there's nothing at the first 3).
What you seem to want as Reese Casey suggests, is a plain object:
const foo = {}; // curly
foo["some string"] = "whatever";
However now the properties are basically unordered. If you want them to be in a guaranteed specific order you do want an array, but all your indicies will need to be integers, and should be sequential. You can achieve this easily by using the .push method:
foo = [];
foo.push("something");
foo.push("something else");
Now foo will have two elements, in the correct order, and index 0 and 1 respectively.
Update based on comment on the other answer:
I want some of the data to be ordered, and the rest of the data to follow
This can be accomplished through object destructuring:
const responseFromDB = {
oneKeyICareAbout: 3,
anotherKeyICareAbout: 2,
foo: 6,
bar: 7,
};
const {
oneKeyICareAbout,
anotherKeyICareAbout,
*rest,
} = responseFromDB;
const stuffToDisplay = [
oneKeyICareAbout,
anotherKeyICareAbout,
...Object.values(rest),
]; // [3, 2, 6, 7]
And at least the destructured stuff you put in the array will be ordered because by doing so you've ordered it.
Javascript arrays cannot have string indexes. This is actually working incorrectly as the index is adding a property to the array object.
Changing to an object makes more sense for this.
EDIT: Whilst below its mentioned you can have string indexes you are not actually using the array by doing so. The answer by Jared Smith goes into much more detail as to why.
The other answers explain what is happening with your array-object mixture. For having an indexable thing which can reproduce the original order, you can use a Map:
The Map object holds key-value pairs and remembers the original insertion order of the keys.
array = new Map();
array.set("one","some data");
array.set("two","some more data");
array.set("3","this should not be the first element");
console.log("Test of get:",array.get("two"));
console.log("Test of order:");
for(let entry of array)
console.log(entry);

What is the difference between using a string or a number to index an array in Javascript? [duplicate]

This question already has answers here:
Is a JavaScript array index a string or an integer?
(5 answers)
Closed 4 years ago.
In Javascript it is possible to use a number (integer) or a string (or a char) to index an array for example:
array[0] = true;
or
array['0'] = true;
Does the computer memory work different depending on how you index the array or is it the exact same thing to do it both ways?
The indexes are stored internally as strings.
But it's more common practise to use numbers to access an array by it's index.
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^³²−1
It's explained in this old post
Below is a snippet that showcases it.
Accessing the index with a string works fine as long that index string only contains digits.
But by expressing the index as a word then it can only be accessed with that word. And console logging the array doesn't show it.
let arr = [0,'a one','a two','a three'];
arr['four'] = 'a four';
arr.push('5');
arr.push(6);
arr.push([7,'7']);
arr.push({a:8, b:'8'});
console.log('\nLog the array:\n\n');
console.log(arr);
console.log('\nAccessing the array:\n\n');
console.log("arr[0]:\t" + arr[0]);
console.log("arr[\'1\']:\t" + arr['1']);
console.log("arr[\'two\']:\t" + arr['two']);
let i=2;
console.log("arr[++i]:\t" + arr[++i]);
console.log("arr[\'four\']:\t" + arr['four']);
console.log('arr[4]:\t'+ arr[4]);
console.log('arr[5]:\t'+ arr[5]);
console.log('\nListing the types in the array:\n\n');
for (var a in arr) console.log(a+'\tindex type: '+ typeof a +', value: '+ arr[a] + ', value type: '+ typeof arr[a]);
And here's a snippet to compare speed between using a number or a string in your browser. It should take roughly the same time.
let arr1 = [];
console.time('Access array through string');
for(let i = 0; i <= 42000000;i++){
arr1['42000000'] = 42;
}
console.timeEnd('Access array through string');
let arr2 = [];
console.time('Access array through integer');
for(let i = 0; i <= 42000000;i++){
arr2[42000000] = 42;
}
console.timeEnd('Access array through integer');
The answer is simple: there is no difference.
Javascript arrays are objects. All keys of objects are strings (or symbols), but never numbers.
Property names must be strings. This means that non-string objects
cannot be used as keys in the object. Any non-string object, including
a number, is typecasted into a string via the toString method. ...see more here
The property accessor [] converts to string first before looking for the property. (some engines may optimize this step and not perform a proper toString call, but it's of no concern here)
So array[0] is interpreted as array['0'].
const a = {
toString: function () {
console.log("a.toString called")
return "1";
}
};
const array = ['a','b','c'];
console.log(array[a]);
When you use quotations for indexing, you're creating a key-value pair in the array. I recommended you stick to numerical notation unless you're intentionally creating those pairs; while array['0'] technically posts to the position, it's bad practice.
Even though myArr['two'] doesn't seem to want to show up in the snippet output, if you hit F12 and look at the console output, you'll clearly see it displayed.
["String 0", "String 1", two: "String 2"]
let myArr = [];
myArr[0] = "String 0";
myArr['1'] = "String 1";
myArr['two'] = "String 2";
console.log(myArr);
As the mdn docs state, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
Arrays are actually just objects that have array-like properties. Keys in JavaScript are strings. So when you see an array, it's actually just a set of key-value pairs, where the keys are index numbers.
Arrays are a special data type. Adding keys that do not correlate to possible indexes are added to an 'object property collection' and are not returned when you use the object.
I think the chrome console does the best job of displaying this:
This array is actually an object with keys of 0 1 2 3, a length property, and a prototype.

find Javascript object length

Im trying to find the length of the report_data(object) key using the below code..but for some reasons it yields value 3.
a={report_freq: "daily", report_item_num: 2, report_num: 39, report_data: "{}"}
Object {report_freq: "daily", report_item_num: 2, report_num: 39, report_data: "{}"}
Object.getOwnPropertyNames(a.report_data).length
3
for more clarity I have the image.
a.report_data is a string with three properties:
0, representing the first character ("{").
1, representing the second character ("}").
and length, representing the length of the string (2).
It's a little counter-intuitive, if you come from other languages, that 0 and 1 are properties, but in Javascript array elements are properties just like all other properties, and "regular" properties can be accessed using array syntax (aka "bracket notation"):
// "array elements"
a.report_data[0] === "{";
a.report_data[1] === "}";
// or...
a.report_data["0"] === "{";
a.report_data["1"] === "}";
// "normal" properties
a.report_data.length === 2;
// or...
a.report_data["length"] === 2;
These are all property names, and, thus, when you ask for an array of property names for your string, you get:
["0", "1", "length"]
Assuming you want the length of the actual string value, then you simply want to use report_data.length, as demonstrated here:
var a = {
report_freq: "daily",
report_item_num: 2,
report_num: 39,
report_data: "{}"
};
console.log(a.report_data.length)
Your current code includes this:
Object.getOwnPropertyNames(a.report_data).length
If you look at the docs for Object.getOwnPropertyNames(obj), you'll see the following description:
Object.getOwnPropertyNames() returns an array whose elements are strings corresponding to the enumerable and non-enumerable properties found directly upon obj.
So, in this case, Object.getOwnPropertyNames(a.report_data) returns an array containing the keys found on the string, and there happens to be 3 of them.

Javascript Arrays In IE 8 issue

As per what I know, arrays in Javascript is nothing but the combination of methods and objects.
Now my task is to display the values of array (say y_array)
I have used for(x in y_array) and then displayed the value.
In mozilla and in IE its working fine, but in IE it displays the first element of array with index as indexOf and value is indexOf(obj, from) which i dont want.
I tried
if(x!='indexOf') { display the array value ; }
It worked and things were fine but there is extensive use of arrays been displayed and I am looking for some permanent fix rather than this hardcoded one.
Can anyone please help me?
You are not the first mixing up arrays and objects. SO should contain a FAQ for this kind of questions ;)
Let's try to explain things:
An array is a row of values, which can be retrieved using their position in the row. The order of the array values is fixed (and may be reordered).
An object is a variable that contains named properties in the form of key-value pairs. The order of the key-value pairs belonging to an object is arbitrary.
An array looks like: [ 'first', 'second', 'third', ..., 'nth' ]
An object looks like: { first:'firstvalue', second:'secondvalue', ..., nth:'nthvalue' }
The first element of an array is the element with index 0 (so the first position in the row has index value 0). You retrieve it using myArray[0]
An object is unordered, so it has no first element. You retrieve any element from it using myObject.somekey or myObject['somekey'].
For arrays you use a loop iterating through the numbered index until the end of the array is reached:
var i=0, len = myArray.length;
for ( i; i<len; i++ ) {
//do something with >>> myArray[i] <<<
}
For objects you use a loop using the key and the in operator (making sure you are only retrieving user defined properties of the object with the .hasOwnAttribute method):
for ( var key in myObject ){
if (myObject.hasOwnProperty(key)) {
// do something with >>> myObject[key] <<<
}
}
Basically, think of an array as a cupboard with drawers, each containing a value. An object can be imagined as a pile of boxes with stickers on the lid, describing the content of the box. Retrieving something from an object, you ask: is there a box with sticker y in pile x and if so, what's in it? Retrieving something from an array, you ask: please give me the contents of drawer nr x.
Now as to your question: the array you are retrieving values for with a for..in loop contains a user defined method, namely indexOf. Using the object style loop for it, the array is treated as object, and the indexOf key (with value like function(){...} I bet) is shown too. IE That's why it may be better to use a traditional for loop with a numeric index when iterating over arrays.
Why is this only in IE? In modern browsers indexOf is a native method of the Array prototype, and native methods are not shown (unless you loop through their prototype that is). IE < 9 doesn't have a native indexOf method for arrays. Somewhere in the scripting you use the method has been added to the Array prototype as a user defined extension.
Bottom line for your problem: don't use for ... in to loop through the values of an array.
For arrays you should use this for loop:
var y_array = [1,2,3,4];
for (var i = 0; i < y_array.length; i++) {
var value = y_array[i];
// do what you want
alert(i + ': ' + value);
}
For objects (objects are like associative arrays - property: value) use this loop:
var y_array = { prop_1 : "value a", prop_2: "value_2", prop_3: 333 }
for (var key in y_array) {
var value = y_array[key];
// do what you want
alert(key + ': ' + value);
}
if there is no value in your json Object like jsobObj = {}. Then you got the indexOf prototype function in side the empty object in IE < 9. (with value like function(){...} I bet) is shown too.
Your can check a condition in side your for Loop. and skip that indexOf.
if(key =='indexOf'){continue;}
E.g :
var jsonObj = { key_1 : "value a", key_2: "value_2", key_3: 333 }
for (var key in y_array) {
if(key == 'indexOf'){continue;} // check if the array contain indexOf
var value = y_array[key];
// do what you want
alert(key + ': ' + value);
}

JavaScript array's length method

Can anyone explain why the second alert says 0 ?
var pollData = new Array();
pollData['pollType'] = 2;
alert(pollData['pollType']); // This prints 2
alert(pollData.length); // This prints 0 ??
The length of the array is only changed when you add numeric indexes. For example,
pollData["randomString"] = 23;
has no effect on length, but
var pollData = [];
pollData["45"] = "Hello";
pollData.length; // 46
changes the length to 46. Note that it doesn't matter if the key was a number or a string, as long as it is a numeric integer.
Besides, you are not supposed to use arrays in this manner. Consider it more of a side effect, since arrays are objects too, and in JavaScript any object can hold arbitrary keys as strings.
Because you haven't put anything into the array yet. You've only been assigning to a dynamically-created pollType attribute on the array object.
If you use numeric indices, then the array automagically takes care of length. For example:
var arr = [ ]; // same as new Array()
arr[2] = 'Banana!';
alert(arr.length); // prints 3 (indexes 0 through 2 were created)
The length property takes into consideration only those members of the array which names are indexes (like '1', '2', '3', ... ).
Arrays in JavaScript have numeric indexes only.
Use an object, which is essentially what you are doing above, setting properties on that array object.
array.length returns how many values are stored in the array. The first alert is returning the value of the position 'pollType'.
The reference guide I always use when needing help with javascript arrays is this page http://www.hunlock.com/blogs/Mastering_Javascript_Arrays
I'd also read what it says under the heading Javascript Does Not Support Associative Arrays, as you may run into problems with this also.
var pollData = Array();
function test() {
pollData[0] = 2
alert(pollData[0]);
alert(pollData.length);
}
//[x] is the array position; hence ['polltype'] is causing issues

Categories

Resources