Eduard Tester
Eduard Tester

Reputation: 135

undefined variables for push or concrat arrays

Can't figure out how to put all variables of PROTOCOL in an new array with an loop function for N PROTOCOL's (same forms as Sequence 1). the problem is, that i earn in all cases different fails(see uncomment OUTPUTS in code) and all the inputs of the "dynamic" arrays are gone after i take a look at the console.log after the loop. its frustrationg as a beginner. thx for help

let NR_i = 0;
let NR_i_end = 7;
let PROTOCOL = new Array();
let PROTOCOL_HTML = new Array();		
let PROTOCOL_CSS = new Array();		
let PROTOCOL_JS = new Array();	
let PROTOCOL_PHP = new Array();		
let PROTOCOL_MySQL = new Array();
let PROTOCOL_CindyJS = new Array();
let PROTOCOL_C_Cpp = new Array();	
let allgemein = [];

//-- Sequence 1 --//
PROTOCOL = [{name:"HTML", index:[].sort()},
	        {name:"CSS", index:[].sort()},
		{name:"JS", index:["document", "getElementById", "var",
		"message", "console", "log"].sort()},
		{name:"PHP", index:["echo"].sort()},
		{name:"MySQL", index:[].sort()},
		{name:"CindyJS", index:[].sort()},
		{name:"Python", index:[].sort()},
		{name:"C_Cpp", index:[].sort()}					
		];
while(NR_i <= NR_i_end) {
  var nameX_2 = [];
  if (PROTOCOL[NR_i].index.length != 0) 
    nameX_2 = 'PROTOCOL_' + PROTOCOL[NR_i].name;
    // OUTPUT - OK: PROTOCOL_JS and so on.
								
    //nameX_2.push(PROTOCOL[NR_i].index);
    // OUTPUT: TypeError: nameX_2.push is not a function
							
    //window[nameX_2].push(PROTOCOL[NR_i].index);
    // OUTPUT: TypeError: Cannot read property 'push' of undefined
								
    //nameX_2 = nameX_2.concat(PROTOCOL[NR_i].index);
    // OUTPUT: PROTOCOL_JSconcat,console, ...
    // Why is PROTOCOL_JS also in? that disturb the hole array

    //nameX_2 = nameX_2.concat(window[PROTOCOL[NR_i].index]);
    // OUTPUT: PROTOCOL_JSundefined

    //nameX_2 = [...nameX_2, ...window[PROTOCOL[NR_i].index]];
    // OUTPUT: TypeError: window[PROTOCOL[NR_i].index] is not iterable

    nameX_2 = [...nameX_2, ...PROTOCOL[NR_i].index];
    // OUTPUT: ["P", "R", "O", "T", "O", "C", "O", "L", 
    //          "_", "J", "S", "concat", "console", and so on
    // Again. Why is PROTOCOL_JS also in? that disturb the hole array
							
    console.log("protocolname_3: ", nameX_2);
  }
  NR_i++;
}
console.log("PROTOCOL_HTML: ",PROTOCOL_HTML);
console.log("PROTOCOL_CS: ",PROTOCOL_CSS);
console.log("PROTOCOL_JS: ",PROTOCOL_JS);
console.log("PROTOCOL_PHP: ",PROTOCOL_PHP);
console.log("PROTOCOL_MySQL: ",PROTOCOL_MySQL);
console.log("PROTOCOL_CindyJS: ",PROTOCOL_CindyJS);
console.log("PROTOCOL_C_Cpp: ",PROTOCOL_C_Cpp);
console.log("nameX_2: ",nameX_2);
// OUTPUT: all empty =/
//-- Sequence 2 --//
// Same struct as Sequence 1, just with different name inputs
//-- Sequence N --//
// Same struct as Sequence 1, just with different name inputs

Upvotes: 1

Views: 200

Answers (3)

Richik SC
Richik SC

Reputation: 884

When you are initializing nameX_2, you are initializing it to an empty array:

var nameX_2 = [];

I assume you want it to be an array as you attempt to push to it later.

However, later, inside your if statement you reassign nameX_2. You reassign it to a String containing 'PROTOCOL_JS'. This is valid in JavaScript and does not throw an error because JS is a dynamically typed language. This means variables in JS can change type, as it does here from an Array to a String.

Then, when you try to .push() an element into nameX_2, it says nameX_2.push is not a function. This is because you are attempting to call .push() on a String, which does not have a .push() method. You probably meant to call it on an array. Likewise, the .concat() method exists on Strings, but simply joins them together end to end.

When you use ... (the spread operator), the string "PROTOCOL_JS" splits into its component characters. This happens because in JavaScript, the spread operator "spreads" objects into its component pieces. For strings, this splits them into characters. For arrays, it splits them into its elements.

You can fix it by replacing the assignment (nameX_2 = 'PROTOCOL_' + PROTOCOL[NR_i].name;) with a .push() call:

nameX_2.push('PROTOCOL_' + PROTOCOL[NR_i].name);

You can also replace your while loop with a for loop, which handles iterator initialization, condition, and increment all in one line. The snippet below should achieve what you are trying to do, assigning the global variables based on the contents of the PROTOCOL array. However, do note that this is bad practice in JavaScript, and it is recommended that you use an object or Map instead.

// Variables must be declared with `var` to access through `this[]`
// Bad practice, use an object.
var PROTOCOL_JS = [];
var PROTOCOL_PHP = [];

let PROTOCOL = [{name:"HTML", index:[].sort()},
	        {name:"CSS", index:[].sort()},
		{name:"JS", index:["document", "getElementById", "var",
		"message", "console", "log"].sort()},
		{name:"PHP", index:["echo"].sort()},
		{name:"MySQL", index:[].sort()},
		{name:"CindyJS", index:[].sort()},
		{name:"Python", index:[].sort()},
		{name:"C_Cpp", index:[].sort()}					
		];

for (let NR_i = 0; NR_i < PROTOCOL.length; NR_i++) {
  var nameX_2 = [];
  if (PROTOCOL[NR_i].index.length != 0) {
    // Find the protocol name
    let protocolName = 'PROTOCOL_' + PROTOCOL[NR_i].name;
    nameX_2.push(...PROTOCOL[NR_i].index);
    this[protocolName]= nameX_2;
    console.log("protocolname_3: ", nameX_2);
  }
}

console.log("PROTOCOL_JS", PROTOCOL_JS);
console.log("PROTOCOL_PHP", PROTOCOL_PHP);

Here is a version that follows good practices and is much cleaner and readable:

let PROTOCOL = [{name:"HTML", index:[].sort()},
	        {name:"CSS", index:[].sort()},
		{name:"JS", index:["document", "getElementById", "var",
		"message", "console", "log"].sort()},
		{name:"PHP", index:["echo"].sort()},
		{name:"MySQL", index:[].sort()},
		{name:"CindyJS", index:[].sort()},
		{name:"Python", index:[].sort()},
		{name:"C_Cpp", index:[].sort()}					
		];

// Object to hold 'indexes' of different protocols.
const protocolIndexes = {};

// `forEach` loop: much cleaner and more concise
PROTOCOL.forEach((protocol) => {
  protocolIndexes[`PROTOCOL_${protocol.name}`] = protocol.index;
});

// Retrieve a specific protocol
console.log("PROTOCOL_JS", protocolIndexes.PROTOCOL_JS);

// Print all protocols
console.log("Protocols: ", protocolIndexes);

Upvotes: 1

Eduard Tester
Eduard Tester

Reputation: 135

I did it so and let me ask if there is an better way to handle that? My problem is also to figure it out if i could make the code smaller.

let PROTOCOL = new Array();
let PROTOCOL_HTML = new Array();        
let PROTOCOL_CSS = new Array();     
let PROTOCOL_JS = new Array();  
let PROTOCOL_PHP = new Array();     
let PROTOCOL_MySQL = new Array();
let PROTOCOL_CindyJS = new Array();
let PROTOCOL_C_Cpp = new Array();   
let NR_i; 
PROTOCOL = [
  {name:"HTML", index:["div","button"].sort()},
  {name:"CSS", index:["background-color","color","border","padding","text-align",
                            "font-size","transition","text-decoration","display","hover"].sort()},
  {name:"JS", index:["document","getElementById","window","addEventListener","click","mouseover","mouseout","change","function","alert", "innerHTML", "Math","random"].sort()},
  {name:"PHP", index:[].sort()},
  {name:"MySQL", index:[].sort()},
  {name:"CindyJS", index:[].sort()},
  {name:"Python", index:[].sort()},
  {name:"C/C++", index:[].sort()}                   
];
for (NR_i = 0; NR_i < PROTOCOL.length; NR_i++) {
  if (PROTOCOL[NR_i].name == "HTML" && PROTOCOL[NR_i].index.length != 0) {
    PROTOCOL_HTML.push(...PROTOCOL[NR_i].index);
  }
  if (PROTOCOL[NR_i].name == "CSS" && PROTOCOL[NR_i].index.length != 0) {
    PROTOCOL_CSS.push(...PROTOCOL[NR_i].index);
  }
  if (PROTOCOL[NR_i].name == "JS" && PROTOCOL[NR_i].index.length != 0) {
    PROTOCOL_JS.push(...PROTOCOL[NR_i].index);
  }
  if (PROTOCOL[NR_i].name == "PHP" && PROTOCOL[NR_i].index.length != 0) {
    PROTOCOL_PHP.push(...PROTOCOL[NR_i].index);
  }
  if (PROTOCOL[NR_i].name == "MySQL" && PROTOCOL[NR_i].index.length != 0) {
    PROTOCOL_MySQL.push(...PROTOCOL[NR_i].index);
  }
  if (PROTOCOL[NR_i].name == "CindyJS" && PROTOCOL[NR_i].index.length != 0) {
    PROTOCOL_CindyJS.push(...PROTOCOL[NR_i].index);
  }
  if (PROTOCOL[NR_i].name == "Pyhon" && PROTOCOL[NR_i].index.length != 0) {
    PROTOCOL_Pyhon.push(...PROTOCOL[NR_i].index);
  }
  if (PROTOCOL[NR_i].name == "C_Cpp" && PROTOCOL[NR_i].index.length != 0) {
    PROTOCOL_C_Cpp.push(...PROTOCOL[NR_i].index);
  }
}

Upvotes: 0

Sam Alexander
Sam Alexander

Reputation: 491

Im not 100% sure what you are asking but, this might help

PROTOCOL = [{name:"HTML", index:[].sort()},
	        {name:"CSS", index:[].sort()},
		{name:"JS", index:["document", "getElementById", "var",
		"message", "console", "log"].sort()},
		{name:"PHP", index:["echo"].sort()},
		{name:"MySQL", index:[].sort()},
		{name:"CindyJS", index:[].sort()},
		{name:"Python", index:[].sort()},
		{name:"C_Cpp", index:[].sort()}					
		];
   
arrays = new Array();
for (i = 0; i < n; i++) {
  arrays[i] = new Array();
  PROTOCOL.forEach(function(value){
    arrays[i].push(value);
  });
};

Upvotes: 2

Related Questions