one of the most important, powerful, useful and least understood techniques in JS
“a way to ‘remember’ and continue to access a function’s scope (its variables) even once the function has finished running”
Example:
functionmakeAdder(x) {
//parameter 'x' is an inner variable
// inner function 'add()' uses 'x', so
// it has a "closure" over it
functionadd(y) {
return y + x;
};
return add;
}
with each call to the outer makeAdder (..) function, the reference to the inner add(..) function gets returned
and add(..) remembers the x value that was passed in to makeAdder(..)
// 'plusOne' gets a reference to the inner 'add(..)'
//function with closure over the 'x' parameter of
// the outer 'makeAdder(..);
var plusOne = makeAdder(1);
//'plusTen' gets a reference to the inner 'add(..)'
// function with closure over the 'x' parameter of
// the outer 'makeAdder(..);
var plusTen = makeAdder(10);
plusOne(3); //4 <-- 1 + 3
plusOne(41); // 42 <-- 1 + 41
plusTen(13); // 23 <-- 10 + 13
How this code works:
call makeAdder(1), get back a reference to its inner add(..) that remembers x as 1 ; name{?} this function reference plusOne(..)
call makeAdder(10), get back another reference to its inner add(..) that remembers x as 10; name{?} this function reference plusTen(..)
call plusOne(3), it adds 3 (its inner y) to the 1 (remembered by x); get 4 as the result
call plusTen(13), it adds 13 (its inner y) to the 10 (remembered by x); get 23 as the result
QUESTIONS:
Is plusTen both a variable name and a function (or function reference)?
What is the difference between function and function reference?
JavaScript: The Definitive Guide, 6th Edition by David Flanagan
3.10 Variable Scope
p53
variable scope/scope of a variable: region of the program source code where the variable is defined
global variable: defined everywhere in JScript code; has global scope
local variable: declared within a function and defined only within the body of the function; local scope
function parameter: count as a local variable
QUESTION: “Defined” here means ‘to have a value’ ?
“Within the body of a function , a local variable takes precedence over a global variable with the same name”; the global variable is ‘hidden’
Example 1:
var scope = "global"; // Declare a global variable
function checkscope() {
var scope = "local"; // Declare a local variable with the same name
return scope; // Return the local value, not the global one
}
checkscope() // => "local"
Example 2: What happens when you don’t use var to declare local variables
scope = "global"; //Declare a global variable, even without var
function checkscope2() {
scope = "local"; // We just changed the global variable
myscope = "local"; // This implicitly declares a new global variable
return [scope, myscope]; // Return two values
}
checkscope2() // => ["local", "local"]: has side effects!
scope // => "local" : global variable has changed
myscope // => "local": global namespace cluttered up
Write a program that creates a string that represents an 8 x 8 grid, using newline characters to separate lines.
At each position of the grid there is either a space or a “#” character.
The characters should form a chess board. Passing this string to console.log should show something like this:
When you have a program that generates this pattern, define a variable size = 8 and change the program so that it works for any size, outputting a grid of the given width and height.
Approach
Loop – “Vertical”:
This will be the outermost for loop
This loop adds height to the output
Let i represent the number of iterations
i is of type number
Let size represent the width and height of the square
size is of type number
By the end of the loop, i == size
Loop – “Horizontal”:
-Increases characters horizontally per line
-Each new line is a new iteration
-Repeating characters: # and a space
-When i is an even number, the line starts with a # character
– Repeated characters when i is an even number: #_
-When i is an odd number, the line starts with a space (will rep. with _ character in notes) -Repeated characters when i is an odd number: #_ , but one _ exists before any repeats
This will be an inner for loop
This loop adds width to the output
Let char represent the characters on the line
char is of type string
char.length returns the length (number of characters) of char
By the end of the loop, i == size == char.length
Questions:
1. How do you repeat string characters horizontally when the number of repeats required is unknown?
You can concatenate strings i.e.
console.log("# " + "# ")
//-> # #
EDIT (after writing Solution Attempt 4 – Final Submission) : You CAN repeat strings horizontally when the number of repeats is unknown.
What is needed: Put console.log outside the for loop (so whatever is printed is the final result of repeated string concatenation). See the next blog post “Exercise 2.3 Part 2” for this solution.
But recall that no arithmetic operation can be applied to strings i.e.
var test = "Hi";
test *= 2;
console.log(test);
//-> NaN
I will not be able to repeat characters horizontally using arithmetic multiplication i.e.
var char = "# " * 3;
console.log(char);
//-> NaN
or
console.log("10" * 2);
//-> 20
console.log(typeof("10" * 2));
//-> number
Observe string concatenation between string values and number values:
Keep in mind that the Number and String functions convert a value to type number and type string respectively.
Though that still isn’t helpful in repeating string characters horizontally when the number of repeats required is unknown.
It passed the mind to replace # and space with 1 and 0, and at the end, replace 1 and 0 with # and space again. Using numbers would allow for repetition via arithmetic operations. However, this idea died a swift death upon the realisation that when a string value’s type is converted to type number, (“10” with 10), any arithmetic operation on this value will be governed by mathematical laws i.e. 10 * 2 = 20, not 1010 i.e.
And why it wouldn’t work with # :
.
.
.
2. What is the update/final-expression in the inner for loop?
Can it be empty?
.
.
.
Outside the scope of Chapter 2, there is a JavaScript String repeat() method. Let’s try this out for Solution 1.
// Allow any size to be inputted
var size = prompt("Enter a positive integer.");
// Convert string value inputted in prompt to type number
Number(size);
// Outer loop to track vertical iteration
for (var i = 0; i <= size; i++) {
// Inner loop to add characters horizontally per line
for(var char = ""; char.length <= size; ) {
//If the line number is odd
if (size % 2 !== 0) {
// Begin the line with a space
char = " ";
// How many times does the pattern have to repeat?
var numRepeats1 = (((size + 1)/2) - 1);
var pattern1 = "# ";
// Concatenate the first space with the pattern
// Use string repeat() method to repeat the pattern the appropriate number of times
char += pattern1.repeat(numRepeats1);
}
//If the line number is even
if (size % 2 == 0) {
//Pattern to be repeated
var pattern2 = "# ";
// Repeat the pattern this amount of times
var numRepeats2 = size/2;
//Update char value
char += pattern2.repeat(numRepeats2);
}
.
.
.
EPIPHANY: I don’t need the second for loop. With the string repeat method, there is no need for a loop to repeat the characters horizontally.
EPIPHANY 2 (after Solution Attempt 1 Test 1): Nevermind, I do need the second loop. Without this loop, a conditional branch would be left out depending on what the value of size is i.e. if size = 2, the odd number if-statement branch is not considered at all, so instead of printing out line 1, line 2, only line 2 with weird stuff is printed.
Solution Attempt 1
var char = ""
var size = prompt("Enter a positive integer.");
Number(size);
for (var i = 0; i <= size; i++) {
if (size % 2 !== 0) {
char = " ";
var pattern1 = "# ";
var numRepeats1 = (((size + 1)/2) - 1);
char += pattern1.repeat(numRepeats1);
console.log(char);
}
if (size % 2 == 0) {
var pattern2 = "# ";
var numRepeats2 = size/2;
char += pattern2.repeat(numRepeats2);
console.log(char);
}}
size = 2
No plan survives first contact with the enemy. I think I’ll become quite fond of that saying.
What I think went wrong:
Firstly, the initial value of i should be set to 1, not zero. This way, the iteration number is equal to the row number (of the output).
size = 2; change is highlighted
Secondly, the if-statement conditions are wrong. Variable i instead of variable size should be used. That is:
// for odd-number lines
if (i % 2 !== 0) {
}
// for even-number lines
if (i % 2 == 0) {
}
Why? Because it is the iteration value that tracks the row that we are on. The value of i increases with each iteration, while the value of size stays the same (it is whatever value was inputted in prompt). Size is the maximum width and height of the grid. We just need the current row number of the grid (i).
Let’s say size = 2. The odd-numbered line if-statement branch {check wording} is evaluated to be false since size is an even-numbered value. That’s why char = ” ” didn’t manifest. Execution moves to the even-numbered line if-statement branch, and its statement body is executed.
NB: The value of i is compared to the value of size at the beginning of each iteration to see if another iteration is required. {check wording and understanding: is the updated value compared with the value in the condition at the END or the BEGINNING of each ITERATION (or do we say LOOP)?}
size = 2; changes are highlighted
What happened?
Look at numRepeats1 and numRepeats2. Are their formulas correct? Seems to be so, yes. Next, look at char +=.
size = 2; change is highlighted
QUESTION 1: Why did a change from Line 17 char += pattern2.repeat(numRepeats2); to char = pattern2.repeat(numRepeats2); give the correct output for the 2nd line?
Testing
1) Line 17 –> char += re-added
Line 7 –> char = “1”
Changes are to see whether the new value of char bleeds out of its if-statement into the rest of the program. Apparently yes. char = “1” should only affect odd number iterations.
size = 2
ANSWER to QUESTION 1: For some reason, the value of char remains “1# # # … #” even when the iteration is a new, even-numbered iteration. That the iteration is even-numbered means that execution should bypass the first if statement (Line 6) and go on to the second if statement (Line 14). char’s value should be an empty string when execution starts at Line 14, not holding on to whatever value it gained from Line 10.
We must also consider the += operator on Line 17. What happens when it is removed?
2) Line 17 –> = operator replaces += operator
size = 2
ANSWER to QUESTION 1: When char (whose value seems to cling to the result from Line 10) is not concatenated to pattern2 on Line 17, the output for iteration number 2 looks proper.
size = 2
if-statement for even-number lines seem to be working properly. Something’s wrong with the if-statement for odd-number lines branch. Suspect are Lines 9 and/or 10.
Looking at Line 9 — changed (((size + 1)/2) – 1); to (size):
Line 9, testing the repeat formula
Testing the repeat formula:
That means something is wrong with char += or size input, not the formula.
EDIT: At least, for when size holds ODD NUMBERS. How about EVEN NUMBERS?
EPIPHANY: Whenever size is an odd number, the repeating formula in the first if-statement works fine. But the repeating formula in the second if-statement doesn’t work properly. AND VICE VERSA. All because of variable size, which is used in the repeating formula. FIX THE FORMULAS.
Repeating a string 2.5 times doesn’t happen. It repeats 2 times.
But the if-statement for odd-number and the if-statement for even numbers should filter incoming numbers, and slide them into their respective formulas.
The String repeat() method and char += … seems to be working fine.
Testing prompt input:
size = 3 ; highlighted is the output you’re supposed to have gotten
Something’s wrong with the prompt input.
More proof:
By process of elimination, these are the remaining potential errors:
Repeating formulas — fix both the odd and even one; use something other than size or adjust the numbers to accommodate variable size
REPEATING PATTERN ISSUE and discrepancy between value of i and value of size
Don’t cheat with using blanks as noncharacters. Spaces count as characters and you want to print the specified character amount, no more no less.
Prompt input
for loop? lack of a secondary loop?
THE BIG EPIPHANY
When size holds an odd number value, the numRepeats1 formula works properly. But the numRepeats2 formula does not. When size holds an even number value, the numRepeats2 formula works properly, but the numRepeats1 formula does not.
The solution:
if size = odd number {
if i = odd number
Adjust repeating formula accordingly
if i = even number
Adjust repeating formula accordingly
}
else if size = even number {
if i = odd number
Adjust repeating formula accordingly
if i = even number
Adjust repeating formula accordingly
}
Place these if statements after the for loop. Each if statement will have a nested if statement (for i = odd number) and else-if statement (for i = even number).
Solution Attempt 2
var char = "";
var size = 2;
Number(size);
for (var i = 1; i <= size; i++) {
// if size is an odd numberif (size % 2 !== 0) {
//if the row number (iteration) is an odd numberif (i % 2 !== 0) {
char = " ";
var pattern1 = "# ";
var numRepeats1 = (((size + 1)/2) - 1);
char += pattern1.repeat(numRepeats1);
console.log(char);
}
//if the row number is an even number if (i % 2 == 0) {
char = "#"
var pattern2 = " #";
var numRepeats2 = ((size -1)/2);
char += pattern2.repeat(numRepeats2);
console.log(char);
}}
//If size is an even number else if (size % 2 == 0) {
//if the row number is odd if (i % 2 !== 0) {
var pattern1 = " #";
var numRepeats1 = (size/2);
char += pattern1.repeat(numRepeats1);
console.log(char);
}
//if the row number is evenif (i % 2 == 0) {
var pattern2 = "# ";
var numRepeats2 = (size/2);
char += pattern2.repeat(numRepeats2);
console.log(char);
}}}
^Makes more structural sense for the currently outermost for loop to be inside “if size is odd” and “if size is even” statements. Is the structure causing the following problem though? This structure, while disorganized, should still work properly.
** “if size is odd” if statement branch is working properly. Something’s wrong with the “if size is even” statement
size = 2
Get rid of += on Line 33:
Highlighted yellow is the change:
size = 2
Why this change when += was replaced by = , on Line 33?
Now there are issues with the += on Line 26:
The pattern marked “2” is the pattern on Line 24, repeated twice. But where did the pattern marked “1” come from?
char += pattern1.repeat(numRepeats1);
//equivalent to:
char = char + pattern1.repeat(numRepeats1);
char should be an empty string, until it is concatenated with pattern1.
Highlighted yellow is the change from += to + on Line 26:
So char = “# # ” when execution hit upon Line 26? QUESTION 2: How?
Using other values for size i.e. 3, 5, 6, 8, 10, the program now displays the proper output. On Line 2, I re-added prompt(), which also works fine now.
EDIT (during Solution Attempt 3): Oh no, prompt() doesn’t work fine for odd numbers.
Solution Attempt 3
1 var char = "";
2 var size = prompt("Enter a positive integer.");
3 Number(size);
4
5 for (var i = 1; i <= size; i++) {
6 if (size % 2 !== 0) {
7 if (i % 2 !== 0) {
8 char = " ";
9 var pattern1 = "# ";
10 var numRepeats1 = (((size + 1)/2) - 1);
11 char += pattern1.repeat(numRepeats1);
12 console.log(char);
13 }
14
15 if (i % 2 == 0) {
16 char = "#";
17 var pattern2 = " #";
18 var numRepeats2 = ((size -1)/2);
19 char += pattern2.repeat(numRepeats2);
20 console.log(char);
21 }}
22 else if (size % 2 == 0) {
23 if (i % 2 !== 0) {
24 var pattern1 = " #";
25 var numRepeats1 = (size/2);
26 char = pattern1.repeat(numRepeats1);
27 console.log(char);
28 }
29
30 if (i % 2 == 0) {
31 var pattern2 = "# ";
32 var numRepeats2 = (size/2);
33 char = pattern2.repeat(numRepeats2);
34 console.log(char);
35 }}}
…
I celebrated too soon.
When size = 11 without prompt(), we get this:
Output is proper as expected
When size = 11 via prompt(), we get this mess:
Inputting size values into prompt() that are even and greater than 10 i.e. 12, 14, 16, etc., the output is proper as expected. However, when inputting size values into prompt() that are ODD and greater than 10 i.e. 11, 13, 15, 17, etc., the output is all wrong.
EDIT: Nope, odd-numbers below 10, when inputted via prompt() for size, also do not work properly.
Therefore, we’re dealing with either an error(s) with 1) Lines 5 – Line 18 (when size is an odd number) or 2) the prompt() method or 3) both or 4) something else.
Note that the even-numbered rows do show the expected output. The odd-numbered rows show more than the expected characters. So the error is somewhere in Lines 6-11 if we’re looking at option 1).
Suspects:
Indentation? Line 13 if statement is indented more than it should be? This is unlikely to be the problem. (Check: Yeah, it isn’t the issue.)
prompt() The main suspect
The += operator on Line 10 (Check: Not the issue.)
usage of same variable for different values i.e. char (Line 7, Line 10) ?? (Check:Not an issue.)
Tentative conclusion: It looks like a prompt() issue, because inputting any value manually gives the correct output. RETURN TO THIS.
Cleaning up the code:
see Solution Attempt 4
defined the variable char, but did not initialize it –> its value is undefined; will give char a value depending on the nested if statement
declared and initialized variables patternsharp and patternspace outside of the for loop –> prevents re-writing these four times inside the loop’s nested if and else if statement bodies
renamed numRepeats1 and numRepeats2 –> under one variable name: numRepeats (see Line 9), because they are contained within their nested if statements
under the else-if statement on Line 19, pulled two numRepeats out of their nested if-statements, and placed it as one numRepeats statement (Line 20) –> this applied to both nest if-statements and saves space (no need to rewrite numRepeats twice since they have the same formula of size/2)
Solution Attempt 4: Final Submission
using String repeat() method
still having issues with prompt()
Solution Attempt 4 with Comments
varchar;varpatternsharp ="# "; varpatternspace =" #";
varsize = 3;Number(size);for(vari = 1; i <= size; i++) {// size is an odd numberif(size % 2 !== 0) {// row number is an odd numberif(i % 2 !== 0) {//odd rows start with a spacechar =" ";
// the number of times patternsharp shoud be repeatedvarnumRepeats = (((size + 1)/2) - 1); /*concatenating " " and patternsharp however many times it's repeated*/ char += patternsharp.repeat(numRepeats); console.log(char);}//row number is an even numberif(i % 2 == 0) {//even rows start with a sharp
char = "#";
//the number of times patternspace should be repeatednumRepeats = ((size-1)/2);char += patternspace.repeat(numRepeats); console.log(char);
}}
//size is an even numberelse if(size % 2 == 0) {/*the number of times patternsharp or patternspace should be repeated */numRepeats = (size/2);//row number is oddif(i % 2 !== 0) { char = patternspace.repeat(numRepeats); console.log(char);
}
//row number is even if(i % 2 == 0) {char = patternsharp.repeat(numRepeats); console.log(char); }}}
QUESTION 3:
I defined and initialized the variable numRepeats on Line 9. The later usage of numRepeats on Lines 15, 21, and 27 do no require being defined again, even when they are inside different if/else-if statements. QUESTION: Was that defining a variable ‘locally’? Versus ‘globally’ before the for loop?
still works properly
QUESTION 4:
What happens when you take out the console.log(char); from the if statement body, and place it outside of it? See Line 13.
For the Future
I didn’t try a solution without String repeat() method. Try that.
Answer Questions 1-4 properly.
Figure out what is wrong with prompt() or Lines 6-11.
Consider other methods to solve Chess Board — replace(), a second for loop, newline character, etc.
Then check your solutions with the Book Solutions.
Data is stored as bits – any kind of two-valued things
Bits – usually described as zeros and ones
Inside the computer, bits – high or low electrical charge, a strong or weak signal, a shiny or dull spot on a CD
“Any piece of discrete information can be reduced to a sequence of zeros and ones and thus represented in bits” {?}
NB: Discrete data can only take distinct values; can be numeric or categorical (male or female, green or yellow) –stackexchange
Example: Show the number 13 in bits
-Have only 2 digits (0 and 1)
-The weight of each digit increases by a factor of 2 from right to left
-The binary number 00001101, or 8+4+1, is the decimal number 13
NB: a binary number is expressed in the binary numeral system or base-2 numeral system which represents numeric values using two different symbols: usually 0 and 1 –Wikipedia
Values
modern computer has > 30 billion bits in its volatile data storage; more in nonvolatile data storage
NB: Volatile memory is computer memory that requires power to maintain the stored info; stored data is lost if the power is off or interrupted —Wikipedia
hard to work with this large quantity of bits
Solution: separate bits into chunks (called values) that represent pieces of information
Every value has a type that determines its role
The 6 basic types of values in JS:
-numbers
-strings
-Booleans
-objects
-functions
-undefined values
To create a value — invoke its name
Every value has to be stored somewhere
Might run out of bits if you use many, many values simultaneously
“When you no longer use a value, it will dissipate {?}, leaving behind its bits to be recycled as building material for the next values”
Numbers
[make more concise]
The value of the number type is a numeric value
JS uses 64 bits to store a single number value
The amount of different numbers that can be represented is limited
With 64 binary digits, 264 different numbers can be represented
Computer memory used to be smaller; 8 bits or 16 bits were used to represent numbers
Easy to overflow such small numbers – end up with a number that did not fit into the given amount of bits
Today, computers have plenty of memory, so overflow occurs only when dealing with astronomical numbers
Bits can store negative numbers (one bit indicates the sign of the number)
Nonwhole numbers must also be represented (some of the bits store the position of the decimal point)
Calculations with integers (whole numbers) are precise
Treat fractional digital numbers as ap and proximations, not as precise values (because fractions cannot be expressed by a finite number of decimal digits — and there is only 64 bits available to store them)
Arithmetic
100 + 4*11
+ and * are operators
+ represents addition
* represents multiplication
<<value>> <<operator>> <<value>>
An operator between two values applies itself to those values to produce a new value
Order of operator application (precedence) is determined by BEDMAS
Apply Left to Right if there are multiple operators with the same precedence
% : represents the remainder operation — known as modulo or remainder
3 JS values considered numbers but don’t behave like normal numbers:
Infinity : positive infinity
-Infinity : negative infinity
NaN : “Not a Number” – a value of the number type; will get NaN when i.e. 0/0 (zero divided by zero), Infinity – Infinity, any numeric operation that does not yield a precise result
Strings
string – a basic data type
represent text
content enclosed in quotes (single, double – but start and end quote must match)
i.e. “Hello there!”, ‘On the way to the moon, hold up.’
Characters that are difficult to place within quotes: quotes, newlines (characters you get when you press Enter – basically spaces on a new line)
Solution: escaping the character — using: backslash (\) — when this is inside a quoted text, it indicates the the character after it has a special meaning
i.e. ‘She\’s my sister\’s dog’ means the quotes are a part of the string
i.e. ‘ \n ‘ means a newline
i.e. ‘ \t ‘ means a tab character
i.e. “This is the first line\nAnd this is the second”
Actual text:
This is the first line
And this is the second
When you want a backslash in a string to be just a backslash:
use \\ (two backslashes)
Example:
console.log(“A newline character is written like \”\\n\”.”)
// -> A newline character is written like “\n”.
Strings cannot be divided, multiplied, or subtracted
+ operator used on strings to concatenate – combines two strings together
Example:
console.log(“con” + “cat” + “e” + “nate”)
// -> concatenate [not enclosed by single quotes like in Python]
Unary Operators
unary operator: operator that takes\operates on one value
binary operator: operator that uses two values
ternary operator: operator that operates on three values
typeof: an unary operator that produces a string value naming the type of the value given to it
Example 1:
console.log(typeof 4.5)
//-> number
Example 2:
console.log(typeof Infinity)
//-> number
Example 3:
console.log(typeof NaN)
//->number
Example 4:
console.log(typeof 3 > 2)
//-> false
Example 5:
console.log(typeof “x”)
//-> string
NB1: console.log() outputs a message to the Web Console (a way for us to see the result of evaluating something)
NB2: The minus operator (-) can be used as both a binary and an unary operator
Example 6:
console.log(-(10-2))
//-> -8
Boolean Values
Distinguish between two possibilities i.e. yes and no, on and off, …
Boolean type: has two values — true and false
Comparisons
A way to produce Boolean values
Example 1:
console.log(3 > 2)
//-> true Indicates 3 is greater than 2
Example 2:
console.log(3 < 2)
//-> false
Strings can be compared to each other :
strings are ordered alphabetically i.e. “a” < “z”
uppercase letters are “less” than lowercase letters i.e. “Z” < “a”
non-alphabetic characters (!, -, ?, etc.) are included in the ordering i.e. “.” > “!”, “?” > “!”
comparison is based on the Unicode standard : assigns a number to every character ever needed, including characters from other languages i.e. Japanese, Arabic, Greek, …
comparing strings : Left to Right, compare numeric codes of characters one by one
other comparison operators: >= greater than or equal to <= less than or equal to == equal to !=not equal to
one value in JS is not equal to itself : NaN (“not a number”)
Example:
console.log(NaN == NaN)
//-> false
NB: NaN denotes the result of a nonsensical computation; therefore it isn’t equal to the result of other nonsensical computations.
Logical Operators
Operators on Boolean values
and, or, not
used to “reason” about Booleans
&& represents logical and -a binary operator
-its result is true iff both values given to it are true
Example 1:
console.log(true && false)
//-> false
Example 2:
console.log(true && true)
//-> true
|| represents logical or
-a binary operator
– proudces true if either of the values given to it is true
Example 1: console.log(false || true)
//-> true
Example 2: console.log(false || false)
//-> false
!represents not
-an unary operator
-flips the value given to it
<<value1>> ? <<value2>> : <<value3>> -represents the conditional/ternary operator
– a ternary operator
-written with a question mark and a colon
– The first value “picks” which of the other two values will come out :
-if true, the second value is chosen
-if false, the third value is chosen
NB: << … >> just represents that a value is written; <<…>> itself is not included in the value
Example 1:
console.log(true ? 1 : 2)
//-> 1
Example 2:
console.log(false ? 1 : 2)
//-> 2
Undefined Values
Two special values:
null
undefined
represent the absence of a meaningful value (carry no information)
NB1: operations that don’t produce a meaningful value yield undefined because they have to yield some value
NB2:
-there is a difference in meaning between undefined and null (but it doesn’t matter most of the time)
-this is an accident of JS’ design
-treat them as interchangeable (for now)
Automatic Type Conversion
Here we’ll see how JS accepts almost any program given to it, even if they are odd.
type coercion: – an operator is applied to the “wrong” type of value i.e. “three” + 3
-JS converts that value to the type it wants
-JS uses a set of unpredictable rules to do this
Example 1:
console.log(8*null)
//-> 0 null becomes 0
Example 2:
console.log(“5” – 1)
//-> 4 string -> number ; “5” becomes 5
Example 3:
console.log(“5” + 1)
//-> 51 + tries string concatenation before numeric addition; 1 converted to “1”
Example 4:
console.log(“five” * 2)
//-> NaN
Example 5:
console.log(false == 0)
//-> true
Regarding Ex. 4: When something that doesn’t map to a number i.e. “five”, “undefined”, is converted to a number, the value NaN is produced.
NB: Further arithmetic operations on NaN keep producing NaN.
Comparing values of different types using ==
most cases: JS converts one of the values to the other value’s type
For true to be produced —
if null is on one side, undefined must be on the other and vice versa
Example 1:
console.log(null == undefined)
//-> true
Example 2:
console.log(undefined == null)
//-> true
Example 3:
console.log(null == 0)
//-> false
Example 4:
console.log(undefined == 1)
//-> false
NB: to test whether a value has a real value instead of null or undefined, compare it to null with the == or != operator.
QUESTION: Can you compare it to undefined too?
Rules for converting strings and numbers to Boolean values:
0, NaN, the empty string (“”) count as false
all other values count as true
Ex. 1:
console.log(0 == false)
//-> true
Ex. 2:
console.log(“” == false)
//-> true
For these cases, automatic type conversion is unwanted.
To test whether something refers to the precise value false:
Use two extra operators:
===
!==
=== tests whether a value is precisely equal to the other
!== tests whether a value is not precisely equal to the other
Ex:
console.log(“” === false)
//-> false
In this example, “” counts as false, but it is not precisely equal to the value false.
NB: Use the three-character comparison operators to make certain that both sides are the same type.
QUESTION: Because automatic type conversion could change the type of a value in the comparison?
Short Circuiting of Logical Operators
Logical operators && and || handle values of different types strangely
They will convert the value on their left side to Boolean type (to decide what to do)
Depending on the operator and the result of that conversion, either the original LH-value or RH-value is returned
|| operator
– returns the value to its left when that can be converted to true
-returns RH-value otherwise
Ex. 1:
console.log(null || “user”)
//-> user
Ex. 2
console.log(“Karl” || “user”)
Karl
NB: Therefore || operator can be used as a way to fall back on a default value i.e. give it an expression that might produce an empty value on the left, the value on the right will be used as a replacement
&& operator
– works the other way around
-when LH-value is something that converts to false, it returns that original LH-value
-otherwise, RH-value is returned
Property of && and || operators: Short-circuit evaluation: expression on right evaluated only when necessary
Ex. 1: true || X
-LH-value is true so the result is true
-X is never evaluated, no what X is
Ex. 2: false && X
-result is false
-X is ignored
Conditional operator
-works similarly
-first expression is always evaluated
-second or third value (the one not picked) is ignored {?}
Summary
We made some values and applied operators to them to get new values.
Went through four types of JS values: numbers, strings, Booleans, undefined values
Values are created by typing in their name (true, false, null, undefined) or value (“abc”, 13)
Unary operators:
-(!) to negate logically
-(-) to negate a number
-(typeof) to find a value’s type
Ternary operator:
( ? : ) – to pick one of two values based on a third value
NaN (“not a number”) is the only JS value not equal to itself, because the result of a nonsensical computation cannot equal the result of another nonsensical computation
Progress: We can now use JS as a pocket calculator. LOL FML.
Resource: Eloquent Javascript, 2nd Edition by Marijn Haverbeke
What is Javascript?
JavaScript (henceforth JS) created in 1995 to add programs to web pages in the Netscape Navigator browser
Major graphical web browsers have since adopted JS
JS has made modern web applications possible
“Modern web applications = applications with which you can interact directly without doing a reload for every action”
Also used in websites to provide interactivity
NB: Netscape – a series of web browsers produced by Netscape Communications Corporation (now a subsidiary of AOL); original browser once the dominant browser in terms of usage share (proportion of visitors to web sites that use a certain web browser), but lost to Internet Explorer in the first browser war (competition for dominance in the usage share of web browsers) (first war — Microsoft’s Internet Explorer vs. Netscape’s Navigator) —Wikipedia: Netscape (web browser)
ECMAScript standard : a standard document that describes the way JS should work to ensure that software claiming to support JS really does support JS ; named after Ecma International, the organization that did the standardization
ECMAScript and JS can be used interchangeably (two names for the same language)
Disadvantages of JS
JS is “ridiculously liberal in what it allows” — almost any command is accepted, but is then interpreted differently
Idea behind this design: make programming in JS easier for beginners
Reality: Makes finding program errors harder because the system will not point them out to you
Advantages of JS
Flexibility allows for many techniques that are impossible in more rigid languages
Different versions
Version 3 — widely supported version btwn ~ 2000-2010, the time of JS’s ascent to dominance
Version 4 — “changing a living, widely used language … turned out to be politically difficult” — work abandoned in 2008
Version 5 — came out in 2009
Version 5.1 — 2011 — Editorial changes —w3schools
Version 6 — 2015 — Added classes and modules —w3schools
This book’s edition came out in 2014 so it will focus on Version 5, which all major browsers support; we should focus on using Version 6, which all major browsers are in the process of supporting
Platforms on which JS is used: Web browsers, databases i.e. MongoDB, CouchDB (use JS as their scripting and query language)
Several platforms for desktop and server programming i.e. notably, Node.js, provides a powerful environment for programming JS outside of the browser