forEach on array of undefined created by Array constructor
Array(5)
is essentialy equivalent to
var arr = [];
arr.length = 5;
In javascript changing array's length doesn't set any values for it's numeric properties nor does it define those properties in the array object. So numeric properties are undefined instead of having undefined value. You can check it by using:
Object.keys(arr)
When iterating javascript iterates through numeric properties of the array, so if these don't exist, there is nothing to iterate over.
You can check it by doing:
var arr = Array(5)
//prints nothing
arr.forEach(function(elem, index, array) {
console.log(index);
});
arr[3] = 'hey'
//prints only 'hey' even though arr.length === 5
arr.forEach(function(elem, index, array) {
console.log(index);
});
The following code:
var arr = [undefined, undefined];
creates and array of length ===2
and sets the both numeric properties 0 and 1 to undefined.
Use forEach to loop over Array(n), array of undefined values
I understand I am not answering to the question directly, bit still I believe this provides good information.
Check what Kyle Simpson said recently about this topic.
Basically,
console.log(new Array(5)) // Chrome: [undefinedx5] Firefox: [ <5 empty slots> ]
and
console.log([undefined, undefined, undefined, undefined, undefined]) // [ undefined, undefined, undefined, undefined, undefined ]
are entirely different value types. And the browser is (kind of) lying to you when it says undefinedx5. Applying .map() over the first case will return nothing, while in the second case you can do operations with the undefined.
From the spec, ecma-262/5.1/#sec-15.4.2.2, the only thing new Array(5)
does, is to create an object of class type Array with length property = 5. The literal array syntax, [], actually places the types (if you give it something) in the slots.
Use forEach to loop over Array(n), array of undefined values
I understand I am not answering to the question directly, bit still I believe this provides good information.
Check what Kyle Simpson said recently about this topic.
Basically,
console.log(new Array(5)) // Chrome: [undefinedx5] Firefox: [ <5 empty slots> ]
and
console.log([undefined, undefined, undefined, undefined, undefined]) // [ undefined, undefined, undefined, undefined, undefined ]
are entirely different value types. And the browser is (kind of) lying to you when it says undefinedx5. Applying .map() over the first case will return nothing, while in the second case you can do operations with the undefined.
From the spec, ecma-262/5.1/#sec-15.4.2.2, the only thing new Array(5)
does, is to create an object of class type Array with length property = 5. The literal array syntax, [], actually places the types (if you give it something) in the slots.
JavaScript: use .map() and .forEach() on new Array() of undefinded
Try this:
const result = Array.apply(null, new Array(5)).map(() => ({name:''}));
console.log(result);
forEach loop quirky behavior with undefined values?
So apparently it is not assigning each value undefined, but only setting its
length
property to whatever is passed in the constructor.
Correct. (Provided you pass only a single argument and it's a number. If you pass a non-number, or pass more than one argument, they're used as elements for the array. So Array("3")
results in ["3"]
; Array(3, 4)
results in [3, 4]
.)
This is not apparent when you log Array(n) to the console because it shows an array with n undefined values.
It depends on what console you use. The devtools in Chromium browsers show (3) [empty x 3]
for exactly that reason, to differentiate between empty array slots and ones containing the value undefined
.
So I guess my main question would be, are there other ways to execute
forEach
andmap
without filling the array or by using the quirky hack I mentioned earlier?
If you want forEach
and map
to visit elements of the array, they have to actually exist. Those methods (and several others) are defined such that they don't call your callback for empty slots in sparse arrays. If by "quirky hack" you mean [...Array(3)]
, that's also filling the array (and is fully-specified behavior: [...x]
uses the iterator x
provides, and the array iterator is defined that it yields undefined
for empty slots rather than skipping them as forEach
, map
, and similar do). Doing that (spreading the sparse array) is one way to create an array filled with undefined
(not empty) elements. Array.fill
is another. Here's a third: Array.from({length: 3})
const a = Array.from({length: 3});
a.forEach(value => {
console.log(`value = ${value}`);
});
forEach with uninitialized array
I'm wondering if someone can explain this to me.
That is the spec.
forEach
and its brethren ignore "holes" in sparse arrays. For more information, see this blog post.
From MDN:
forEach()
executes the provided callback once for each element present in the array
The spec says the same thing.
Strange array constructor behavior with forEach
MDN on forEach
forEach()
executes the provided callback once for each element present in the array in ascending order. It is not invoked for indexes that have been deleted or elided. However, it is executed for elements that are present and have the value undefined.
The way you're initializing the array does set it's length, but doesn't set the values in the array to anything, so forEach
doesn't iterate over those elements:
If the argument
len
is a Number andToUint32(len)
is equal tolen
, then the length property of the newly constructed object is set toToUint32(len)
.
Example:
var a = Array(5);
a.forEach(function(element){ console.log('First log:', element)});
a[2] = true;a[3] = undefined;
a.forEach(function(element){ console.log('Second log:', element)});
var b = [];b[999] = 'Foobar';
b.forEach(function(element){ console.log('Third log:', element)});
Why does `.forEach` work on dense arrays but not on sparse arrays?
- If they both have the same length, indexes, and values how is one iterable but the other isn't?
These functions are explicitly documented to perform this way. Both arrays are iteratable, but forEach
/map
/etc explicitly skips indices which are not in the array:
var sparse = new Array(3);
var dense = Array.apply(null, Array(3)); // See dense array link belo
1 in sparse; // false
1 in dense; // true
// Sparse can still be iterated over
sparse[100] = 'a'
sparse.forEach(function (n, i) { console.log(n, i) }); // a 100
- What is the reason for the difference?
Presumably an explicit decision was made to omit indices which don't exist
- What is the best way to determine if an array is sparse or dense?
You can use the following:
function isSparse(array) {
for (var i = 0; i < array.length; ++i) {
if (!i in array)
return true;
return false;
}
RE: Your comment
There has got be a reason for why [,,,] doesn't have indexes but [undefined, undefined, undefined] does.
There doesn't have to be a reason, that's just the way they're built. One has keys, the other doesn't.
Look:
Object.keys(Array(3)) // => []
Object.keys(['a','b']) // => ["0", "1"]
The forEach is undefined in a Javascript Class Method
DEFINITIVE SOLUTION
where were problem?
What's solution?
The #createMemberList()
generate an array with more than 220 rows. Then, it's necessary wait a while for Of()
method to process everything.
For it, it's must to use setTimeout()
function in the method, like this:
setTimeout(()=>{
console.log(JSON.stringify(this.membersList))
},3000)
The code will to stay like this:
const $INIT = {
GetMembers: class{
#listaOrdenadaItens;
#listaMembros;
#MemberListOfChurch;
membersList;
#linkGFile="https://cdn.jsdelivr.net/gh/OficialLeonardoLima/cdn@main/json_test.json";
constructor(ListFromGD){
if(typeof ListFromGD!=="undefined"&&ListFromGD!==null){
this.#linkGFile=ListFromGD;
}
this.#createMemberList();
setTimeout(()=>{
console.log(JSON.stringify(this.membersList))
},3000)
document.querySelector("#console").text=JSON.stringify(this.membersList)
}
/*Members List*/
Of(ChurchName){
/**Filters member data according congregation
* Usage: new $INIT.GetMembers().Of("ChurchName")
*/
this.#MemberListOfChurch=[];;
this.ChurchName=ChurchName;
setTimeout(()=>{
this.membersList.forEach((item, count) => {
console.log("Why this code don't appears in console?");
if (/^[a-zA-Z_À-Úà-ú\s]{2,50}$/.test(ChurchName)==true && ChurchName.toLocaleLowerCase() == item.congregacao.toLocaleLowerCase()) {
this.#MemberListOfChurch[count] = item;
}else{
console.log("Trys to check anyone error");
}
});
},3000);
return this.#MemberListOfChurch;
}
#getListaOrdenada (){
return [
/**Personal Informations */
"Nome Completo",
"Sexo",
"CPF",
"Data de Nascimento",
"RG",
"Orgão Emissor",
"UF_RG",
"Data de Expedição",
"Estado Civil",
"CONJUGE",
"Naturalidade",
"UF_NAT",
"NOME_PAI",
"NOME_MAE",
/**Schooling and ecclesiastical data */
"GRAU_INSTRUCAO",
"PROFISSAO",
"FUNCAO_ECLESIASTICA",
"LOCAL",
"UF_BATISMO",
/**Address informations */
"Endereco",
"cep",
"bairro",
"cidade",
"uf",
"congregacao",
"contact_number",
"whatsapp_number"
]
}
#createMemberList(){
var listaOrdenada = this.#getListaOrdenada();
/**Create an array */
var NewListMember = [];
var DadosMembros={};
/**
* Gets registered members list at system!
*/
this.#getJSON(this.#linkGFile).then(response=>{
response.values.forEach((item, i)=>{
/**Examina membro por membro aqui */
if(item[0]===undefined)return;
/**Creates a name for array of values: Ex: {"Complete Name" : "Leonardo Lima de Sousa"} */
listaOrdenada.forEach((ItemName,N)=>{
if(ItemName===undefined) return;
DadosMembros[ItemName]=item[N];
});
NewListMember[i] = DadosMembros;
DadosMembros={};
});
})
this.membersList=NewListMember;
}
#getJSON=async t=>{const r=await fetch(t);if(!r.ok)throw new Error(r.statusText);return r.json()};
}
}
Related Topics
What Advantages Does Using (Function(Window, Document, Undefined) { ... })(Window, Document) Confer
Use Dynamic (Variable) String as Regex Pattern in JavaScript
Foreach on Array of Undefined Created by Array Constructor
Binding Multiple Events to a Listener (Without Jquery)
How to Apply CSS to the Elements Within an Iframe
How to Draw Polygons on an HTML5 Canvas
How to Abort Image <Img> Load Requests Without Using Window.Stop()
How to Play HTML5 Video in Reverse
What Are Some Methods to Debug JavaScript Inside of a Uiwebview
Jquery Validation Using the Class Instead of the Name Value
Angular2:Render a Component Without Its Wrapping Tag
Write/Add Data in JSON File Using Node.Js
Settimeout Ignores Timeout? (Fires Immediately)
How to Convert an Iso Date to the Date Format Yyyy-Mm-Dd
Uncaught Referenceerror: $ Is Not Defined Error in Jquery
".Addeventlistener Is Not a Function" Why Does This Error Occur