-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDebugging.js
More file actions
482 lines (349 loc) · 19.2 KB
/
Debugging.js
File metadata and controls
482 lines (349 loc) · 19.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
/* Use the JavaScript Console to Check the Value of a Variable
Both Chrome and Firefox have excellent JavaScript consoles, also known as DevTools, for debugging your JavaScript.
You can find Developer tools in your Chrome's menu or Web Console in Firefox's menu. If you're using a different browser, or a mobile phone, we strongly recommend switching to desktop Firefox or Chrome.
The console.log() method, which "prints" the output of what's within its parentheses to the console, will likely be the most helpful debugging tool. Placing it at strategic points in your code can show you the intermediate values of variables. It's good practice to have an idea of what the output should be before looking at what it is. Having check points to see the status of your calculations throughout your code will help narrow down where the problem is.
Here's an example to print the string Hello world! to the console:
console.log('Hello world!');
Use the console.log() method to print the value of the variable a where noted in the code.
*/
let a = 5;
let b = 1;
a++;
// Only change code below this line
console.log(a);
let sumAB = a + b;
console.log(sumAB);
/* Should :
Your code should use console.log() to check the value of the variable a.
*/
/* Understanding the Differences between the freeCodeCamp and Browser Console
You may have noticed that some freeCodeCamp JavaScript challenges include their own console. This console behaves a little differently than the browser console you used in the last challenge.
The following challenge is meant to highlight the main difference between the freeCodeCamp console and your browser console.
When you run ordinary JavaScript, the browser's console will display your console.log() statements the exact number of times it is called.
The freeCodeCamp console will print your console.log() statements a short time after the editor detects a change in the script, as well as during testing.
The freeCodeCamp console is cleared before the tests are run and, to avoid spam, only prints the logs during the first test (see the note below for exceptions).
If you would like to see every log for every test, run the tests, and open the browser console. If you prefer to use the browser console, and want it to mimic the freeCodeCamp console, place console.clear() before any other console calls, to clear the browser console.
Note: console.logs inside functions are printed to the freeCodeCamp console whenever those functions are called. This can help debugging functions that are called during testing.
First, use console.log to log the output variable. Then, use console.clear to clear the browser console.
*/
// Open your browser console.
let output = "Get this to log once in the freeCodeCamp console and twice in the browser console";
// Use console.log() to print the output variable.
console.log(output);
// Run the tests to see the difference between the two consoles.
console.clear();
// Now, add console.clear() before your console.log() to clear the browser console, and pass the tests.
/* Should :
Passed
You should use console.clear() to clear the browser console.
Passed
You should use console.log() to print the output variable.
*/
/* Use typeof to Check the Type of a Variable
You can use typeof to check the data structure, or type, of a variable. This is useful in debugging when working with multiple data types. If you think you're adding two numbers, but one is actually a string, the results can be unexpected. Type errors can lurk in calculations or function calls. Be careful especially when you're accessing and working with external data in the form of a JavaScript Object Notation (JSON) object.
Here are some examples using typeof:
console.log(typeof "");
console.log(typeof 0);
console.log(typeof []);
console.log(typeof {});
In order, the console will display the strings string, number, object, and object.
JavaScript recognizes six primitive (immutable) data types: Boolean, Null, Undefined, Number, String, and Symbol (new with ES6) and one type for mutable items: Object. Note that in JavaScript, arrays are technically a type of object.
Add two console.log() statements to check the typeof each of the two variables seven and three in the code.
*/
let seven = 7;
let three = "3";
console.log(seven + three);
// Only change code below this line
// Turn to
let seven = 7;
let three = "3";
console.log(seven + three);
// Only change code below this line
console.log(typeof seven);
console.log(typeof three);
/* Should :
Your code should use typeof in two console.log() statements to check the type of the variables.
Passed
Your code should use typeof to check the type of the variable seven.
Passed
Your code should use typeof to check the type of the variable three.
*/
/*Catch Misspelled Variable and Function Names
The console.log() and typeof methods are the two primary ways to check intermediate values and types of program output. Now it's time to get into the common forms that bugs take. One syntax-level issue that fast typers can commiserate with is the humble spelling error.
Transposed, missing, or mis-capitalized characters in a variable or function name will have the browser looking for an object that doesn't exist - and complain in the form of a reference error. JavaScript variable and function names are case-sensitive.
Fix the two spelling errors in the code so the netWorkingCapital calculation works.
*/
let receivables = 10;
let payables = 8;
let netWorkingCapital = recievables - payable;
console.log(`Net working capital is: ${netWorkingCapital}`);
// Turn to
let receivables = 10;
let payables = 8;
let netWorkingCapital = receivables - payables;
console.log(`Net working capital is: ${netWorkingCapital}`);
/* Should :
Check the spelling of the two variables used in the netWorkingCapital calculation, the console output should show that "Net working capital is: 2".
Passed
There should be no instances of mis-spelled variables in the code.
Passed
The receivables variable should be declared and used properly in the code.
Passed
There should be no instances of mis-spelled variables in the code.
Passed
The payables variable should be declared and used properly in the code.
*/
/* Catch Unclosed Parentheses, Brackets, Braces and Quotes
Another syntax error to be aware of is that all opening parentheses, brackets, curly braces, and quotes have a closing pair. Forgetting a piece tends to happen when you're editing existing code and inserting items with one of the pair types. Also, take care when nesting code blocks into others, such as adding a callback function as an argument to a method.
One way to avoid this mistake is as soon as the opening character is typed, immediately include the closing match, then move the cursor back between them and continue coding. Fortunately, most modern code editors generate the second half of the pair automatically.
Fix the two pair errors in the code.
*/
let myArray = [1, 2, 3;
let arraySum = myArray.reduce((previous, current => previous + current);
console.log(`Sum of array values is: ${arraySum}`);
// Turn to
let myArray = [1, 2, 3];
let arraySum = myArray.reduce((previous, current) => previous + current);
console.log(`Sum of array values is: ${arraySum}`);
/* Should :
Your code should fix the missing piece of the array.
Your code should fix the missing piece of the .reduce() method. The console output should show that Sum of array values is: 6.
*/
/* Catch Mixed Usage of Single and Double Quotes
JavaScript allows the use of both single (') and double (") quotes to declare a string. Deciding which one to use generally comes down to personal preference, with some exceptions.
Having two choices is great when a string has contractions or another piece of text that's in quotes. Just be careful that you don't close the string too early, which causes a syntax error.
Here are some examples of mixing quotes:
const grouchoContraction = "I've had a perfectly wonderful evening, but this wasn't it.";
const quoteInString = "Groucho Marx once said 'Quote me as saying I was mis-quoted.'";
const uhOhGroucho = 'I've had a perfectly wonderful evening, but this wasn't it.';
The first two are correct, but the third is incorrect.
Of course, it is okay to use only one style of quotes. You can escape the quotes inside the string by using the backslash (\) escape character:
const allSameQuotes = 'I\'ve had a perfectly wonderful evening, but this wasn\'t it.';
Fix the string so it either uses different quotes for the href value, or escape the existing ones. Keep the double quote marks around the entire string.
*/
let innerHtml = "<p>Click here to <a href="#Home">return home</a></p>";
console.log(innerHtml);
// Turn to
let innerHtml = "<p>Click here to <a href=\"#Home\">return home</a></p>";
console.log(innerHtml);++
/* Should :
Your code should fix the quotes around the href value #Home by either changing or escaping them.
Passed
Your code should keep the double quotes around the entire string.
*/
/*Catch Use of Assignment Operator Instead of Equality Operator
Branching programs, i.e. ones that do different things if certain conditions are met, rely on if, else if, and else statements in JavaScript. The condition sometimes takes the form of testing whether a result is equal to a value.
This logic is spoken (in English, at least) as "if x equals y, then ..." which can literally translate into code using the =, or assignment operator. This leads to unexpected control flow in your program.
As covered in previous challenges, the assignment operator (=) in JavaScript assigns a value to a variable name. And the == and === operators check for equality (the triple === tests for strict equality, meaning both value and type are the same).
The code below assigns x to be 2, which evaluates as true. Almost every value on its own in JavaScript evaluates to true, except what are known as the "falsy" values: false, 0, "" (an empty string), NaN, undefined, and null.
let x = 1;
let y = 2;
if (x = y) {
} else {
}
In this example, the code block within the if statement will run for any value of y, unless y is falsy. The else block, which we expect to run here, will not actually run.
Fix the condition so the program runs the right branch, and the appropriate value is assigned to result.
*/
let x = 7;
let y = 9;
let result = "to come";
if(x = y) {
result = "Equal!";
} else {
result = "Not equal!";
}
console.log(result);
// Turn to
let x = 7;
let y = 9;
let result = "to come";
if(x === y) {
result = "Equal!";
} else {
result = "Not equal!";
}
console.log(result);
/* Should :
Your code should fix the condition so it checks for equality, instead of using assignment.
Passed
The condition should use either == or === to test for equality.
*/
/* Catch Missing Open and Closing Parenthesis After a Function Call
When a function or method doesn't take any arguments, you may forget to include the (empty) opening and closing parentheses when calling it. Often times the result of a function call is saved in a variable for other use in your code. This error can be detected by logging variable values (or their types) to the console and seeing that one is set to a function reference, instead of the expected value the function returns.
The variables in the following example are different:
function myFunction() {
return "You rock!";
}
let varOne = myFunction;
let varTwo = myFunction();
Here varOne is the function myFunction, and varTwo is the string You rock!.
Fix the code so the variable result is set to the value returned from calling the function getNine.
*/
function getNine() {
let x = 6;
let y = 3;
return x + y;
}
let result = getNine;
console.log(result);
// Turn to
function getNine() {
let x = 6;
let y = 3;
return x + y;
}
let result = getNine();
console.log(result);
/* Should :
Your code should fix the variable result so it is set to the number that the function getNine returns.
Passed
Your code should call the getNine function.
*/
/* Catch Arguments Passed in the Wrong Order When Calling a Function
Continuing the discussion on calling functions, the next bug to watch out for is when a function's arguments are supplied in the incorrect order. If the arguments are different types, such as a function expecting an array and an integer, this will likely throw a runtime error. If the arguments are the same type (all integers, for example), then the logic of the code won't make sense. Make sure to supply all required arguments, in the proper order to avoid these issues.
The function raiseToPower raises a base to an exponent. Unfortunately, it's not called properly - fix the code so the value of power is the expected 8.
*/
function raiseToPower(b, e) {
return Math.pow(b, e);
}
let base = 2;
let exp = 3;
let power = raiseToPower(exp, base);
console.log(power);
// Turn to
function raiseToPower(b, e) {
return Math.pow(b, e);
}
let base = 2;
let exp = 3;
let power = raiseToPower(base, exp);
console.log(power);
/* Should :
Your code should fix the variable power so it equals 2 raised to the 3rd power, not 3 raised to the 2nd power.
Passed
Your code should use the correct order of the arguments for the raiseToPower function call.
*/
/* Catch Off By One Errors When Using Indexing
Off by one errors (sometimes called OBOE) crop up when you're trying to target a specific index of a string or array (to slice or access a segment), or when looping over the indices of them. JavaScript indexing starts at zero, not one, which means the last index is always one less than the length of the item. If you try to access an index equal to the length, the program may throw an "index out of range" reference error or print undefined.
When you use string or array methods that take index ranges as arguments, it helps to read the documentation and understand if they are inclusive (the item at the given index is part of what's returned) or not. Here are some examples of off by one errors:
let alphabet = "abcdefghijklmnopqrstuvwxyz";
let len = alphabet.length;
for (let i = 0; i <= len; i++) {
console.log(alphabet[i]);
}
for (let j = 1; j < len; j++) {
console.log(alphabet[j]);
}
for (let k = 0; k < len; k++) {
console.log(alphabet[k]);
}
The first example here loops one too many times, and the second loops one too few times (missing the first index, 0). The third example is correct.
Fix the two indexing errors in the following function so all the numbers 1 through 5 are printed to the console.
*/
function countToFive() {
let firstFive = "12345";
let len = firstFive.length;
// Only change code below this line
for (let i = 1; i <= len; i++) {
// Only change code above this line
console.log(firstFive[i]);
}
}
countToFive();
// Turn to
function countToFive() {
let firstFive = "12345";
let len = firstFive.length;
// Only change code below this line
for (let i = 0; i < len; i++) {
// Only change code above this line
console.log(firstFive[i]);
}
}
countToFive();
/* Should :
Your code should set the initial condition of the loop so it starts at the first index.
Passed
Your code should fix the initial condition of the loop so that the index starts at 0.
Passed
Your code should set the terminal condition of the loop so it stops at the last index.
Passed
Your code should fix the terminal condition of the loop so that it stops at 1 before the length.
*/
/* Use Caution When Reinitializing Variables Inside a Loop
Sometimes it's necessary to save information, increment counters, or re-set variables within a loop. A potential issue is when variables either should be reinitialized, and aren't, or vice versa. This is particularly dangerous if you accidentally reset the variable being used for the terminal condition, causing an infinite loop.
Printing variable values with each cycle of your loop by using console.log() can uncover buggy behavior related to resetting, or failing to reset a variable.
The following function is supposed to create a two-dimensional array with m rows and n columns of zeroes. Unfortunately, it's not producing the expected output because the row variable isn't being reinitialized (set back to an empty array) in the outer loop. Fix the code so it returns a correct 3x2 array of zeroes, which looks like [[0, 0], [0, 0], [0, 0]].
*/
function zeroArray(m, n) {
// Creates a 2-D array with m rows and n columns of zeroes
let newArray = [];
let row = [];
for (let i = 0; i < m; i++) {
// Adds the m-th row into newArray
for (let j = 0; j < n; j++) {
// Pushes n zeroes into the current row to create the columns
row.push(0);
}
// Pushes the current row, which now has n zeroes in it, to the array
newArray.push(row);
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);
// Turn to
function zeroArray(m, n) {
// Creates a 2-D array with m rows and n columns of zeroes
let newArray = [];
for (let i = 0; i < m; i++) {
// Adds the m-th row into newArray
let row = [];
for (let j = 0; j < n; j++) {
// Pushes n zeroes into the current row to create the columns
row.push(0);
}
// Pushes the current row, which now has n zeroes in it, to the array
newArray.push(row);
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);
/* Should :
Your code should set the matrix variable to an array holding 3 rows of 2 columns of zeroes each.
Passed
The matrix variable should have 3 rows.
Passed
The matrix variable should have 2 columns in each row.
Passed
zeroArray(4,3) should return an array holding 4 rows of 3 columns of zeroes each.
*/
/* Prevent Infinite Loops with a Valid Terminal Condition
The final topic is the dreaded infinite loop. Loops are great tools when you need your program to run a code block a certain number of times or until a condition is met, but they need a terminal condition that ends the looping. Infinite loops are likely to freeze or crash the browser, and cause general program execution mayhem, which no one wants.
There was an example of an infinite loop in the introduction to this section - it had no terminal condition to break out of the while loop inside loopy(). Do NOT call this function!
function loopy() {
while(true) {
console.log("Hello, world!");
}
}
It's the programmer's job to ensure that the terminal condition, which tells the program when to break out of the loop code, is eventually reached. One error is incrementing or decrementing a counter variable in the wrong direction from the terminal condition. Another one is accidentally resetting a counter or index variable within the loop code, instead of incrementing or decrementing it.
The myFunc() function contains an infinite loop because the terminal condition i != 4 will never evaluate to false (and break the looping) - i will increment by 2 each pass, and jump right over 4 since i is odd to start. Fix the comparison operator in the terminal condition so the loop only runs for i less than or equal to 4.
*/
function myFunc() {
for (let i = 1; i != 4; i += 2) {
console.log("Still going!");
}
}
// Turn to
function myFunc() {
for (let i = 1; i != 4; i += 2) {
console.log("Still going!");
}
}
/* Should :
Your code should change the comparison operator in the terminal condition (the middle part) of the for loop.
Passed
Your code should fix the comparison operator in the terminal condition of the loop.
*/
// END