Unregistered member of array in length property JS - javascript

I came across this code that is used to keep both forward and reverse reference in an array:
var arr = [];
arr[arr['A'] = 0] = 'A';
arr[arr['B'] = 1] = 'B';
// On node interpreter
arr // [ 'A', 'B', A: 0, B: 1 ]
arr["A"] // 0
arr["B"] // 1
arr[0] // 'A'
arr[1] // 'B'
arr[2] // 'undefined'
arr.length // 2
The A: 0, B: 1 members get pushed to the end of the array.
What are these members and what happened in the process so that .length property recorded 2 instead of 4?

Storing a value with a string key into an array does not actually modify the array. It only adds a dynamic field to the Array object, unlike storing with a numeric index, which actually pushes a value into the array.. Array.length only reflects the number of elements in the array, as managed by the array, but not the number of dynamic fields in the array.

var arr = [];
arr["A"] = 2;
Here you are adding a property to the array object which does not reflect over the number of elements in the array.In javascript, elements of array are always stored using indices.
Array.length always returns the number of elements stored in the array.

Related

Javascript delete object items leaves null traces [duplicate]

What is the difference between using the delete operator on the array element as opposed to using the Array.splice method?
For example:
myArray = ['a', 'b', 'c', 'd'];
delete myArray[1];
// or
myArray.splice (1, 1);
Why even have the splice method if I can delete array elements like I can with objects?
delete will delete the object property, but will not reindex the array or update its length. This makes it appears as if it is undefined:
> myArray = ['a', 'b', 'c', 'd']
["a", "b", "c", "d"]
> delete myArray[0]
true
> myArray[0]
undefined
Note that it is not in fact set to the value undefined, rather the property is removed from the array, making it appear undefined. The Chrome dev tools make this distinction clear by printing empty when logging the array.
> myArray[0]
undefined
> myArray
[empty, "b", "c", "d"]
myArray.splice(start, deleteCount) actually removes the element, reindexes the array, and changes its length.
> myArray = ['a', 'b', 'c', 'd']
["a", "b", "c", "d"]
> myArray.splice(0, 2)
["a", "b"]
> myArray
["c", "d"]
Array.remove() Method
John Resig, creator of jQuery created a very handy Array.remove method that I always use it in my projects.
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
and here's some examples of how it could be used:
// Remove the second item from the array
array.remove(1);
// Remove the second-to-last item from the array
array.remove(-2);
// Remove the second and third items from the array
array.remove(1,2);
// Remove the last and second-to-last items from the array
array.remove(-2,-1);
John's website
Because delete only removes the object from the element in the array, the length of the array won't change. Splice removes the object and shortens the array.
The following code will display "a", "b", "undefined", "d"
myArray = ['a', 'b', 'c', 'd']; delete myArray[2];
for (var count = 0; count < myArray.length; count++) {
alert(myArray[count]);
}
Whereas this will display "a", "b", "d"
myArray = ['a', 'b', 'c', 'd']; myArray.splice(2,1);
for (var count = 0; count < myArray.length; count++) {
alert(myArray[count]);
}
I stumbled onto this question while trying to understand how to remove every occurrence of an element from an Array. Here's a comparison of splice and delete for removing every 'c' from the items Array.
var items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];
while (items.indexOf('c') !== -1) {
items.splice(items.indexOf('c'), 1);
}
console.log(items); // ["a", "b", "d", "a", "b", "d"]
items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];
while (items.indexOf('c') !== -1) {
delete items[items.indexOf('c')];
}
console.log(items); // ["a", "b", undefined, "d", "a", "b", undefined, "d"]
​
From Core JavaScript 1.5 Reference > Operators > Special Operators > delete Operator :
When you delete an array element, the
array length is not affected. For
example, if you delete a[3], a[4] is
still a[4] and a[3] is undefined. This
holds even if you delete the last
element of the array (delete
a[a.length-1]).
As stated many times above, using splice() seems like a perfect fit. Documentation at Mozilla:
The splice() method changes the content of an array by removing existing elements and/or adding new elements.
var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
myFish.splice(2, 0, 'drum');
// myFish is ["angel", "clown", "drum", "mandarin", "sturgeon"]
myFish.splice(2, 1);
// myFish is ["angel", "clown", "mandarin", "sturgeon"]
Syntax
array.splice(start)
array.splice(start, deleteCount)
array.splice(start, deleteCount, item1, item2, ...)
Parameters
start
Index at which to start changing the array. If greater than the length of the array, actual starting index will be set to the length of the array. If negative, will begin that many elements from the end.
deleteCount
An integer indicating the number of old array elements to remove. If deleteCount is 0, no elements are removed. In this case, you should specify at least one new element. If deleteCount is greater than the number of elements left in the array starting at start, then all of the elements through the end of the array will be deleted.
If deleteCount is omitted, deleteCount will be equal to (arr.length - start).
item1, item2, ...
The elements to add to the array, beginning at the start index. If you don't specify any elements, splice() will only remove elements from the array.
Return value
An array containing the deleted elements. If only one element is removed, an array of one element is returned. If no elements are removed, an empty array is returned.
[...]
splice will work with numeric indices.
whereas delete can be used against other kind of indices..
example:
delete myArray['text1'];
It's probably also worth mentioning that splice only works on arrays. (Object properties can't be relied on to follow a consistent order.)
To remove the key-value pair from an object, delete is actually what you want:
delete myObj.propName; // , or:
delete myObj["propName"]; // Equivalent.
delete Vs splice
when you delete an item from an array
var arr = [1,2,3,4]; delete arr[2]; //result [1, 2, 3:, 4]
console.log(arr)
when you splice
var arr = [1,2,3,4]; arr.splice(1,1); //result [1, 3, 4]
console.log(arr);
in case of delete the element is deleted but the index remains empty
while in case of splice element is deleted and the index of rest elements is reduced accordingly
delete acts like a non real world situation, it just removes the item, but the array length stays the same:
example from node terminal:
> var arr = ["a","b","c","d"];
> delete arr[2]
true
> arr
[ 'a', 'b', , 'd', 'e' ]
Here is a function to remove an item of an array by index, using slice(), it takes the arr as the first arg, and the index of the member you want to delete as the second argument. As you can see, it actually deletes the member of the array, and will reduce the array length by 1
function(arr,arrIndex){
return arr.slice(0,arrIndex).concat(arr.slice(arrIndex + 1));
}
What the function above does is take all the members up to the index, and all the members after the index , and concatenates them together, and returns the result.
Here is an example using the function above as a node module, seeing the terminal will be useful:
> var arr = ["a","b","c","d"]
> arr
[ 'a', 'b', 'c', 'd' ]
> arr.length
4
> var arrayRemoveIndex = require("./lib/array_remove_index");
> var newArray = arrayRemoveIndex(arr,arr.indexOf('c'))
> newArray
[ 'a', 'b', 'd' ] // c ya later
> newArray.length
3
please note that this will not work one array with dupes in it, because indexOf("c") will just get the first occurance, and only splice out and remove the first "c" it finds.
If you want to iterate a large array and selectively delete elements, it would be expensive to call splice() for every delete because splice() would have to re-index subsequent elements every time. Because arrays are associative in Javascript, it would be more efficient to delete the individual elements then re-index the array afterwards.
You can do it by building a new array. e.g
function reindexArray( array )
{
var result = [];
for( var key in array )
result.push( array[key] );
return result;
};
But I don't think you can modify the key values in the original array, which would be more efficient - it looks like you might have to create a new array.
Note that you don't need to check for the "undefined" entries as they don't actually exist and the for loop doesn't return them. It's an artifact of the array printing that displays them as undefined. They don't appear to exist in memory.
It would be nice if you could use something like slice() which would be quicker, but it does not re-index. Anyone know of a better way?
Actually, you can probably do it in place as follows which is probably more efficient, performance-wise:
reindexArray : function( array )
{
var index = 0; // The index where the element should be
for( var key in array ) // Iterate the array
{
if( parseInt( key ) !== index ) // If the element is out of sequence
{
array[index] = array[key]; // Move it to the correct, earlier position in the array
++index; // Update the index
}
}
array.splice( index ); // Remove any remaining elements (These will be duplicates of earlier items)
},
you can use something like this
var my_array = [1,2,3,4,5,6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';})); // [1,2,3,4,6]
The difference can be seen by logging the length of each array after the delete operator and splice() method are applied. For example:
delete operator
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3];
console.log(trees); // ["redwood", "bay", "cedar", empty, "maple"]
console.log(trees.length); // 5
The delete operator removes the element from the array, but the "placeholder" of the element still exists. oak has been removed but it still takes space in the array. Because of this, the length of the array remains 5.
splice() method
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.splice(3,1);
console.log(trees); // ["redwood", "bay", "cedar", "maple"]
console.log(trees.length); // 4
The splice() method completely removes the target value and the "placeholder" as well. oak has been removed as well as the space it used to occupy in the array. The length of the array is now 4.
Performance
There are already many nice answer about functional differences - so here I want to focus on performance. Today (2020.06.25) I perform tests for Chrome 83.0, Safari 13.1 and Firefox 77.0 for solutions mention in question and additionally from chosen answers
Conclusions
the splice (B) solution is fast for small and big arrays
the delete (A) solution is fastest for big and medium fast for small arrays
the filter (E) solution is fastest on Chrome and Firefox for small arrays (but slowest on Safari, and slow for big arrays)
solution D is quite slow
solution C not works for big arrays in Chrome and Safari
function C(arr, idx) {
var rest = arr.slice(idx + 1 || arr.length);
arr.length = idx < 0 ? arr.length + idx : idx;
arr.push.apply(arr, rest);
return arr;
}
// Crash test
let arr = [...'abcdefghij'.repeat(100000)]; // 1M elements
try {
C(arr,1)
} catch(e) {console.error(e.message)}
Details
I perform following tests for solutions
A
B
C
D
E (my)
for small array (4 elements) - you can run test HERE
for big array (1M elements) - you can run test HERE
function A(arr, idx) {
delete arr[idx];
return arr;
}
function B(arr, idx) {
arr.splice(idx,1);
return arr;
}
function C(arr, idx) {
var rest = arr.slice(idx + 1 || arr.length);
arr.length = idx < 0 ? arr.length + idx : idx;
arr.push.apply(arr, rest);
return arr;
}
function D(arr,idx){
return arr.slice(0,idx).concat(arr.slice(idx + 1));
}
function E(arr,idx) {
return arr.filter((a,i) => i !== idx);
}
myArray = ['a', 'b', 'c', 'd'];
[A,B,C,D,E].map(f => console.log(`${f.name} ${JSON.stringify(f([...myArray],1))}`));
This snippet only presents used solutions
Example results for Chrome
Why not just filter? I think it is the most clear way to consider the arrays in js.
myArray = myArray.filter(function(item){
return item.anProperty != whoShouldBeDeleted
});
They're different things that have different purposes.
splice is array-specific and, when used for deleting, removes entries from the array and moves all the previous entries up to fill the gap. (It can also be used to insert entries, or both at the same time.) splice will change the length of the array (assuming it's not a no-op call: theArray.splice(x, 0)).
delete is not array-specific; it's designed for use on objects: It removes a property (key/value pair) from the object you use it on. It only applies to arrays because standard (e.g., non-typed) arrays in JavaScript aren't really arrays at all*, they're objects with special handling for certain properties, such as those whose names are "array indexes" (which are defined as string names "...whose numeric value i is in the range +0 ≤ i < 2^32-1") and length. When you use delete to remove an array entry, all it does is remove the entry; it doesn't move other entries following it up to fill the gap, and so the array becomes "sparse" (has some entries missing entirely). It has no effect on length.
A couple of the current answers to this question incorrectly state that using delete "sets the entry to undefined". That's not correct. It removes the entry (property) entirely, leaving a gap.
Let's use some code to illustrate the differences:
console.log("Using `splice`:");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length); // 5
a.splice(0, 1);
console.log(a.length); // 4
console.log(a[0]); // "b"
console.log("Using `delete`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length); // 5
delete a[0];
console.log(a.length); // still 5
console.log(a[0]); // undefined
console.log("0" in a); // false
console.log(a.hasOwnProperty(0)); // false
console.log("Setting to `undefined`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length); // 5
a[0] = undefined;
console.log(a.length); // still 5
console.log(a[0]); // undefined
console.log("0" in a); // true
console.log(a.hasOwnProperty(0)); // true
* (that's a post on my anemic little blog)
Others have already properly compared delete with splice.
Another interesting comparison is delete versus undefined: a deleted array item uses less memory than one that is just set to undefined;
For example, this code will not finish:
let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
ary.push(y);
ary[y] = undefined;
y += 1;
}
console(ary.length);
It produces this error:
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.
So, as you can see undefined actually takes up heap memory.
However, if you also delete the ary-item (instead of just setting it to undefined), the code will slowly finish:
let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
ary.push(x);
ary[x] = undefined;
delete ary[x];
x += 1;
}
console.log(`Success, array-length: ${ary.length}.`);
These are extreme examples, but they make a point about delete that I haven't seen anyone mention anywhere.
function remove_array_value(array, value) {
var index = array.indexOf(value);
if (index >= 0) {
array.splice(index, 1);
reindex_array(array);
}
}
function reindex_array(array) {
var result = [];
for (var key in array) {
result.push(array[key]);
}
return result;
}
example:
var example_arr = ['apple', 'banana', 'lemon']; // length = 3
remove_array_value(example_arr, 'banana');
banana is deleted and array length = 2
Currently there are two ways to do this
using splice()
arrayObject.splice(index, 1);
using delete
delete arrayObject[index];
But I always suggest to use splice for array objects and delete for object attributes because delete does not update array length.
If you have small array you can use filter:
myArray = ['a', 'b', 'c', 'd'];
myArray = myArray.filter(x => x !== 'b');
I have two methods.
Simple one:
arr = arr.splice(index,1)
Second one:
arr = arr.filter((v,i)=>i!==index)
The advantage to the second one is you can remove a value (all, not just first instance like most)
arr = arr.filter((v,i)=>v!==value)
OK, imagine we have this array below:
const arr = [1, 2, 3, 4, 5];
Let's do delete first:
delete arr[1];
and this is the result:
[1, empty, 3, 4, 5];
empty! and let's get it:
arr[1]; //undefined
So means just the value deleted and it's undefined now, so length is the same, also it will return true...
Let's reset our array and do it with splice this time:
arr.splice(1, 1);
and this is the result this time:
[1, 3, 4, 5];
As you see the array length changed and arr[1] is 3 now...
Also this will return the deleted item in an Array which is [3] in this case...
Easiest way is probably
var myArray = ['a', 'b', 'c', 'd'];
delete myArray[1]; // ['a', undefined, 'c', 'd']. Then use lodash compact method to remove false, null, 0, "", undefined and NaN
myArray = _.compact(myArray); ['a', 'c', 'd'];
Hope this helps.
Reference: https://lodash.com/docs#compact
For those who wants to use Lodash can use:
myArray = _.without(myArray, itemToRemove)
Or as I use in Angular2
import { without } from 'lodash';
...
myArray = without(myArray, itemToRemove);
...
delete: delete will delete the object property, but will not reindex
the array or update its length. This makes it appears as if it is
undefined:
splice: actually removes the element, reindexes the array, and changes
its length.
Delete element from last
arrName.pop();
Delete element from first
arrName.shift();
Delete from middle
arrName.splice(starting index,number of element you wnt to delete);
Ex: arrName.splice(1,1);
Delete one element from last
arrName.splice(-1);
Delete by using array index number
delete arrName[1];
If the desired element to delete is in the middle (say we want to delete 'c', which its index is 1), you can use:
var arr = ['a','b','c'];
var indexToDelete = 1;
var newArray = arr.slice(0,indexToDelete).combine(arr.slice(indexToDelete+1, arr.length))
IndexOf accepts also a reference type. Suppose the following scenario:
var arr = [{item: 1}, {item: 2}, {item: 3}];
var found = find(2, 3); //pseudo code: will return [{item: 2}, {item:3}]
var l = found.length;
while(l--) {
var index = arr.indexOf(found[l])
arr.splice(index, 1);
}
console.log(arr.length); //1
Differently:
var item2 = findUnique(2); //will return {item: 2}
var l = arr.length;
var found = false;
while(!found && l--) {
found = arr[l] === item2;
}
console.log(l, arr[l]);// l is index, arr[l] is the item you look for
Keep it simple :-
When you delete any element in an array, it will delete the value of the position mentioned and makes it empty/undefined but the position exist in the array.
var arr = [1, 2, 3 , 4, 5];
function del() {
delete arr[3];
console.log(arr);
}
del(arr);
where as in splice prototype the arguments are as follows. //arr.splice(position to start the delete , no. of items to delete)
var arr = [1, 2, 3 , 4, 5];
function spl() {
arr.splice(0, 2);
// arr.splice(position to start the delete , no. of items to delete)
console.log(arr);
}
spl(arr);
function deleteFromArray(array, indexToDelete){
var remain = new Array();
for(var i in array){
if(array[i] == indexToDelete){
continue;
}
remain.push(array[i]);
}
return remain;
}
myArray = ['a', 'b', 'c', 'd'];
deleteFromArray(myArray , 0);
// result : myArray = ['b', 'c', 'd'];

Giving string index with number

I was testing giving index as a string to array. But I noticed that array converts string index to number.
for example: A["1"] turns to with A[1]
Can I give a number as a string to array index?
A["1"] = 1;
A["3"] = 3;
expected output:
[ 1: 1, 3: 3 ]
output:
[ <1 empty item>, 1, <1 empty item>, 3 ]
like as usual string index arrays;
A["a"] = 1;
A["c"] = 3;
output:
[ a: 1, c: 3 ]
I think you are confusing objects and arrays.
An array is just a list of items:
const array = [1,2,3,4,5]
// You can access its items by index:
array[0] => 1
array['1'] => 2
An object is a list of key-value pairs and keys are strings:
const obj = { a: 1, b: 2 }
// You can access its item values by key:
array.a => 1
array['b'] => 2
All property names are strings, So array like numeric property names really aren't any different from any other property names.
Javascript arrays cannot have "string indexes". A Javascript Array is exclusively numerically indexed. When you set a "string index", you're setting a property of the object.
A.a = '1' and A['a'] = '1' are equals.
So I think you need to use object. You can do this to get the same output.
function test() {
// A["1"] = 1;
// A["3"] = 3;
let A = {
1: 1,
3: 3
};
return A;
}
output
{ '1': 1, '3': 3 }
Everything in JavaScript is an Object.
Array too. It's just has some special properties and notation. An array is an Object where values are stored in key value pair. Keys are index of an array and values are elements.
For example:
const a = [1,2,4,6]
Object.keys(a) // iterating through keys will give you indexes [0,1,2,3]
There is just one catch. If you provide index of an array as non negative Integer, it will push value to array else all values will be associated as object.
So
a["a"]=1 // [1,2,4,6, a:1], length of an array will be 4 and key a can be accessed as property
Hope it helps.

Sparse arrays and reduce in JavaScript

One would think that in JavaScript:
var array = [1,2,undefined,4];
is the same as:
var array = [1,2];
array.length = 3;
array.push(4);
but it's not. This code shows it:
var array1 = [1,2];
array1.length = 3;
array1.push(4);
var array2 = [1,2,undefined,4];
traverseArray(array1);
traverseArray(array2);
function traverseArray(array) {
console.log("trying: " + array);
console.log("reduce:");
array.reduce(function(prev, current, index, array) {
if(current === undefined) {
console.log("Found undefined");
}
console.log(index+": " +current);
}, undefined);
console.log("for loop:")
for(var i=0;i < array.length;i++) {
var current = array[i];
console.log(i+": " +current);
}
console.log();
}
Output:
trying: 1,2,,4
reduce:
0: 1
1: 2
3: 4
for loop:
0: 1
1: 2
2: undefined
3: 4
trying: 1,2,,4
reduce:
0: 1
1: 2
Found undefined
2: undefined
3: 4
for loop:
0: 1
1: 2
2: undefined
3: 4
Why is undefined in array1 not the same as undefined in array2 and why does the for loop act the same but reduce does not?
array1 has three numerically-named properties: 0, 1, and 3.
array2 has four numerically-named properties: 0, 1, 2, and 3. The value of the property named 2 happens to be undefined.
When you ask an object for the value of a property it doesn't have, the result is undefined.
In the for loop, you ask each array for the values of its properties named 0, 1, 2, and 3. For array1, the property named 2 does not exist, so the property access produces undefined. For array2, the property does exist, but its value actually is undefined, so you get the same result.
On the other hand, reduce only operates on properties that actually exist. From the ECMAScript specification, this is how reduce loops over arrays, using a counter k:
Repeat, while k < len
Let Pk be ToString(k).
Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
If kPresent is true, then... [use the value at index k for the reduce call]
So, we can see that an index is only used if passes a [[HasProperty]] check. array1 does not have a property named 2, so that index is skipped.
apsillers nailed it in the comments . . . the difference is that in array2 you have actually assigned an undefined value to the 3rd element in the array (i.e., at index 2), where as, in array1, you have two elements initially, change the length property, and then add a third element in the forth position.
Here are the relevent sections from MDN that explains why the distinction is important:
From the page on Array.length:
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 says nothing about the number of defined values in the array.
From the page on Array.push():
The push method relies on a length property to determine where to start inserting the given values.
The key here, is really that the length property is really, simple a property that is in no way inherantly tied to the contents of the array. It is simply because the various methods of Array also happen to maintain that property, as they "do their work", that I behaves as if it is.
So, as a result, in array2, the code is actually reporting back the undefined value that you assigned to array2[2], whereas, with array1, the code is interpreting the absence of a value at array1[2] as undefined.

Should I use curly brackets {} or square brackets [] in this case?

Currently I have an array using an increasing index:
var idx = 1;
var a = [];
a[idx++] = "apple";
a[idx++] = "orange";
...
console.log(a[2]);
And only accessing it by [], not using array specific functions, like length, indexOf, ...
Apparently following is also working in this case:
var a = {};
So, which one should I prefer in such case? For example any performance difference between them?
[ ] denotes an array. Arrays only hold values:
var a1 = [1, 2, 3, 4]
As #Qantas pointed out, array can hold more than just values. An array can even contain another array and/or object:
var a2 = [1, 2, ["apple", "orange"], {one: "grape", two: "banana"}];
{ } denotes an object. Objects have key-value pairs like
var a3 = {one: 1, two: 2}
In your case, it's really a matter of how you would like to be able to access the data. If you are only interested in knowing "apple", "pear", etc. Go ahead and use an array. You can access it via it's index
a1[0]; // outputs 1
a1[1]; // outputs 2
or you can iterate over it with a loop. If you use the curly braces, (given the example I gave) you could access it with
a3.one; // outputs 1
a3["two"]; // outputs 2
It's really up to you on how it would best fit your needs in this case. For a more extensive discussion see this article.
The difference is using square brackets will create an Array object while using curly brackets creates a plain object. For example:
a = [];
a[1] = 'a';
b = {};
b[1] = 'b';
a.length; // returns 2
b.length; // is undefined
a.push('z'); // add 'z' to the end of a
b.push('z'); // generates an error - undefined is not a function
// because plain objects don't have a push method
Read the MDN documentation on Array objects to know more about arrays: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

Maintaining array order in Javascript

I am new to JavaScript and I am having trouble working with my array, I want my array ordered how I explicitly write it and not how JavaScript decides it wants it.
If we have a array
var array = {
0: 'zero',
4: 'four',
2: 'two'
};
When I choose to display this in the console, or iterate over it, Its reordered like this
array = {
0: 'zero',
2: 'two',
4: 'four'
};
I have tried 2 loops so far, The for loop, and also the for loop with the in statement.
Both work according how I assumed they would as they use a key and work there way up/down, making order I specify is absolutely useless.
How can I write/print/work with my array as its ordered, In other languages such as PHP its as simple as
$array = array(
0 => 'zero',
4 => 'four',
2 => 'two'
);
foreach($array as $key => $value)
echo $key ."\n";
This would output
0
4
2
Thanks in advance.
You're using an object {}, not an array []. Objects have no explicit order, where Arrays do. That's why you're having your problem. Change your {} to [] and you'll be fine. You could even use an array of objects.
var array = [
{0: 'zero'},
{4: 'four'},
{2: 'two'}
];
Looping over that like so
for(var i = 0; i < array.length; i++){
console.log(array[i]);
}
Gives us our normal order.
Object {0: "zero"}
Object {4: "four"}
Object {2: "two"}
Another Edit: The problem is you're trying to have an array that has properties and values just like an object, without using an object, {property: value} - that can't really be done with an array. To loop over an array like you want, it's as simple as
var arr = [1,2,3]
and
for(var i = 0; i < arr.length; i++){
console.log(i) //1,2,3
}
but the problem, like mentioned above, is you want more complex arrays which you simply can't do.
You need to understand what an Array and what an Object are, they are fundamentally different things and do not behave the same.
Array
Arrays are list-like objects whose prototype has methods to perform traversal and mutation operations. Neither the length of a JavaScript array nor the types of its elements are fixed. Since an array's size length grow or shrink at any time, JavaScript arrays are not guaranteed to be dense. In general, these are convenient characteristics; but if these features are not desirable for your particular use, you might consider using typed arrays.
Examples of an Array, note the magical length property, the values assigned to an Array are always found at their indexed locations; index is from 0 to 2^32 - 1
// dense arrays
var array1 = [1, 2, 3];
array1.length === 3;
array1[0] === 1;
var array2 = [];
array2[0] = 1;
array2[1] = 2;
array2[2] = 3;
array2.length === 3;
array1[1] === 2;
var array3 = [];
array3.push(1);
array3.push(2);
array3.push(3);
array3.length === 3;
array3[2] === 3;
// and a sparse array
var array4 = [];
array4[0] = 1;
array4[2] = 2;
array4[4] = 3;
array4.length === 5;
array4[1] === undefined;
Iterating an array for
var array = [1, 2, 3, 4, 5];
for (var index = 0; index < array.length; index += 1) { // counts from (index) 0 to 4
console.log(index, array[index]); // outputs 0 1 \n 1 2 \n 2 3 \n 3 4 \n 4 5
}
Object
An object is a collection of properties, and a property is an association between a name and a value. A property's value can be a function, in which case the property is known as a method. In addition to objects that are predefined in the browser, you can define your own objects.
Examples of an Object, there is no magical length property.
var object1 = {
'zero': 1,
'one': 2,
'two': 3
};
object1.zero === 1;
var object2 = {);
object2['zero'] = 1;
object2['one'] = 2;
object2['two'] = 3;
object2.one === 2;
var object3 = {);
object3.zero = 1;
object3.one = 2;
object3.two = 3;
object['two'] === 3;
Iterating (enumerating) an object for..in
var object = {
one: 0,
two: 1,
three: 2
};
for (var property in object) {
if (object.hasOwnProperty(property)) { // make sure the property belongs to object
console.log(property, object[property]); // outputs (not necessarily this order)
// three 2 \n two 1 \n one 0
}
};
If you are trying to maintain an ordered Object, then this is not how Javascript works and iteration (enumeration) of an object is arbitrary. There are techniques that you can use to iterate (enumerate) an Object in a known order. This requires that you keep an ordered list of properties in an array and use the array in the iteration process.
var object = {
'c': 1,
'z': 2,
'b': 3,
'a': 4
}
var propertyOrder = ['c', 'z', 'b', 'a'];
for (var index = 0; index < propertyOrder.length; index += 1) {
console.log(index, propertyOrder[index], object[propertyOrder[index]]); // outputs 0 c 1 \n 1 z 2 \n 2 b 3 \n 3 a 4
}
I don't get it. What makes you think that 0, then 4, then 2, is in any form or shape "in order"?
However, apparently what you want is to keep the number and the string together, in the order that you specify.
Your mistake, if you'll excuse me for perhaps sounding a bit harsh, is that you seem to think that you can use indices or member names to be both a means to access data and part of the data itself.
You can't, and you shouldn't. An index is an index, a name is a name, and data is data [1].
Here are two implementations of keeping your numbers and strings together:
var pairs = [
[0, "zero"],
[4, "four"],
[2, "two"]
];
for (var index in pairs) {
alert(pairs[index][0] + ": " + pairs[index][1]);
};
For this one, I keep the pairs of numbers and strings together in arrays of their own: the numbers at position 0, the strings at position 1. I store these arrays in pairs.
Then I iterate over array with for/in, which, in each iteration, gives me an index of my pairs array.
I then use that index to access the right sub-array in pairs, and get the number from position 0 and the string from position 1.
var pairs = [
{number: 0, string: "zero"},
{number: 4, string: "four"},
{number: 2, string: "two"}
];
for (var index in pairs) {
alert(pairs[index].number + ": " + pairs[index].string);
};
This one works exactly the same, except of storing the pairs in arrays, I store them in objects.
This has the added bonus of better readability inside the for loop: pairs[index][0] and pairs[index][1] do not really convey a clear meaning. It tells us nothing more than, "of the pair with the given index, get items 0 and 1".
However, pairs[index].number and pairs[index].name are much clearer: "of the pair with the given index, give me the number and the name."
_
Footnotes:
[1a] A number is a number: my bank account number is just that: a means to identify my bank account. It doesn't convey any meaning as to my name, my PIN, or the balance on my account -- all attributes that would qualify as data belonging to my bank account.
[1b] A name is a name: my name is just a name. When you're talking about me, you can use my name to refer to me, so that others know whom you are talking about. My name does not convey any information about my hobbies, my SSN, or what brand of car I have -- all attributes that would qualify as data that would describe certain aspects of me. (However, by convention, you can often tell a person's gender by their name)

Categories