diff --git a/notes/chap3_types_values_and_variables.md b/notes/chap3_types_values_and_variables.md index 470728f..1254a0d 100644 --- a/notes/chap3_types_values_and_variables.md +++ b/notes/chap3_types_values_and_variables.md @@ -598,16 +598,224 @@ function equalArrays(a, b) { ## 3.9 Type Conversions +**Implicit Conversion**: JS can convert values to its required data type automatically + +```js +10 + " objects" // => "10 objects": Number 10 converts to a string +"7" * "4" // => 28: both strings convert to numbers +let n = 1 - "x"; // n == NaN; string "x" can't convert to a number +n + " objects" // => "NaN objects": NaN converts to string "NaN" +``` + +* Primitive-to-primitive conversion: Refer to [JS primitive-to-primitive conversion table](https://riptutorial.com/javascript/example/16970/primitive-to-primitive-conversion-table) for details +* Object-to-primitive conversion: some more complicated + ### 3.9.1 Conversions and Equality +Two equality operators used JS to test whether 2 values are equal: +* **strict equality operator**: `===`, two operands are not equal if they are not of same type +* **flexible equality operator**: `==`, JS can convert types + +```js +null == undefined // => true: These two values are treated as equal. +"0" == 0 // => true: String converts to a number before comparing. +0 == false // => true: Boolean converts to number before comparing. +"0" == false // => true: Both operands convert to 0 before comparing! +``` + +§4.9.1 explain conversion performed by `==` operator + ### 3.9.2 Explicit Conversions -### 3.9.3 Objbect to Primitive Conversions +Explicit conversion is needed for customized requirements. + +#### Simplist explicit conversion + +Using functions: +* `Boolean()` +* `Number()` +* `Boolean()` + +```js +Number("3") // => 3 +String(false) // => "false": Or use false.toString() +Boolean([]) // => true +``` + +Using `.toString()` method: +* All value (except `null` & `undefined`) has `toString()` method. +* Result is as same as `String()` + +Legacy from the past: `Boolean`, and other functions can be used as constructor with `new`. It create **wrapper** object that behaves just like a primitive. Don't use it + +#### Use some JS operators + +* `+` or `-`: if one operand is string, it convert another to string +* `!`: first convert operand to a boolean, then negate/revert it. + +```js +x + "" // => String(x) ++x // => Number(x) +x-0 // => Number(x) +!!x // => Boolean(x): Note double ! +``` + +#### Formatting & Parsing number + +Convert Number class object to string using `toString()`: +* which accept optional argument for radix (基数) + +```js +let n = 17; +let binary = "0b" + n.toString(2); // binary == "0b10001" +let octal = "0o" + n.toString(8); // octal == "0o21" +let hex = "0x" + n.toString(16); // hex == "0x11" +``` + +Convert Number class object to string, with control over number of decimal places: +* `.toFixed()`: string with specified number of digits after the decimal point. +* `.toExponential()`: string in exponential notation; given specified number of digits after decimal point. +* `.toPrecision()`: string with number of significant digits you specify. (即有几个可见数位) + +```js +let n = 123456.789; +n.toFixed(0) // => "123457" +n.toFixed(2) // => "123456.79" +n.toFixed(5) // => "123456.78900" +n.toExponential(1) // => "1.2e+5" +n.toExponential(3) // => "1.235e+5" +n.toPrecision(4) // => "1.235e+5" +n.toPrecision(7) // => "123456.8" +n.toPrecision(10) // => "123456.7890" +``` + +#### Parsing string to number + +Problem of `Number()`: +* Only accept integer or floating-point +* Only worked for base-10 integers +* Does not allow trailing characters (string). e.g. `10blahblah` + +Solution: +* `parseInt()` + * global function; parse only integers; + * if begin with "0x" or "0X", interpret it as hex + * Accept optional 2nd argument specifying radix +* `parseFloat()` + * global function; parse both integer and floating-point numbers; + +Both `parseInt()` & `parseFloat()`: +* skip leading whitespace +* parse as many numeric characters as they can +* Ignore all following char + +```js +parseInt("3 blind mice") // => 3 +parseFloat(" 3.14 meters") // => 3.14 +parseInt("-12.34") // => -12 +parseInt("0xFF") // => 255 +parseInt("0xff") // => 255 +parseInt("-0XFF") // => -255 +parseFloat(".1") // => 0.1 +parseInt("0.1") // => 0 +parseInt(".1") // => NaN: integers can't start with "." +parseFloat("$72.47") // => NaN: numbers can't start with "$" + +parseInt("11", 2) // => 3: (1*2 + 1) +parseInt("ff", 16) // => 255: (15*16 + 15) +parseInt("zz", 36) // => 1295: (35*36 + 35) +parseInt("077", 8) // => 63: (7*8 + 7) +parseInt("077", 10) // => 77: (7*10 + 7) +``` + +### 3.9.3 Object to Primitive Conversions + +JS has complicated rule to convert objects to primitive values. + +TODO: finish this section ## 3.10 Variable Declaration and Assignment +Binding a name to a value = "assigning a value to a *variable*", variable's value can change as program runs. + +Steps of using variable in JS: +1. **declare** variable using `let` `const` keywords (in ES6) +2. Use declared/initialized variable + ### 3.10.1 Declarations with `let` and `const` +Declare variable in modern JS (ES6 and later): +* `let` keyword: e.g. `let i;` +* multi-variables supported: e.g. `let i, sum;` +* **Initialized** variable is recommanded: e.g. `let message = "hello";` + * Uninitilized variable's value is `undefined` until assigned with value. + +Declare a constant using `const`: +* constant variable need initilization at the same time +* Their value cannot be changed ever, otherwise, cause `TypeError` +* Convention: constant are **capital letters**: e.g. `HTTP_NOT_FOUND` + +```js +const H0 = 74; // Hubble constant (km/s/Mpc) +const C = 299792.458; // Speed of light in a vacuum (km/s) +const AU = 1.496E8; // Astronomical Unit: distance to the sun (km) +``` + +#### Variable and constant scope + +Block scope (Same as in C/C++) +* Variable declared outside code blocks are **global variables** + +#### Repeated declarations + +* Declare multiple vars in a same scope with same name is **syntax error** + * It's not when it's in nested scope + +```js +const x = 1; // Declare x as a global constant +if (x === 1) { + let x = 2; // Inside a block x can refer to a different value + console.log(x); // Prints 2 +} +console.log(x); // Prints 1: we're back in the global scope now +let x = 3; // ERROR! Syntax error trying to re-declare x +``` + +#### Declarations and types + +* In statically typed language (e.g. C/C++ or Java), variable declaration is to specify type of value +* No type associated with JS declaration. A JS variable can hold any type + +```js +let i = 10; +i = "ten"; +``` + ### 3.10.2 Variable Declarations with `var` +Before ES6 +* Declare a variable using `var` +* No constant declaration + +`var` syntax: +* similar as `let` + +```js +var x; +var data = [], count = data.length; +for(var i = 0; i < count; i++) console.log(data[i]); +``` + +`var` vs. `let`: +* Scope of `var`: **Function scope** + * variables declared with `var` do not have (nested) block scope. The only scope they have is the function that containing them. +* Global variable using `var`: + * if `var` used outside of a function body, it declare a global variable + * Global variable declared with `var` are implemented as properties of the global object, which can be referenced using `globalThis`. e.g. + * in function, declare `var x = 2`; from program's view, it's same as `globalThis.x = 2` + * variable declared by `let` & `const` are not global object property +* `var` allows redeclare, due to function scope (instead of block scope) +* variable decalred with `var`, its declaration is lifted up (**hosted**) to top of enclosing function +* Refer to [Stack Overflow: What's the difference-between-using-let-and-var](https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var) + ### 3.10.3 Destructuring Assignment \ No newline at end of file