Studied up to Chap3.6
parent
4942e000b8
commit
60babc0a8a
|
@ -0,0 +1,535 @@
|
|||
# Chapter 3. Types, Values, and Variables
|
||||
|
||||
## 3.1 Overview and Definitions
|
||||
|
||||
JS types has 2 categories of data types:
|
||||
* **primitive** types: numeric, string, boolean, special JS values (`null` & `undefined`)
|
||||
* **object** types: any JS values that not primitive types.
|
||||
* It's a collection of properties where each property has a name and a value (primitive or object)
|
||||
* Ordinary JS object is unordered collection of named values.
|
||||
* Special JS object like
|
||||
* **Array** defined in JS is an ordered collection of numbered values.
|
||||
* **Map**: mapping from keys to values
|
||||
* **Set**: set of values
|
||||
* **"typed array" types** for operations on array of bytes/binary
|
||||
* **RegExp** for textual patterns
|
||||
* **Date** type for date & times
|
||||
* **Error & subtypes** for errors when executing JS code.
|
||||
|
||||
Functional Programming of JS:
|
||||
* Functions/Classes are not just part of language syntax, but they are also values that can be manipulated by JS
|
||||
|
||||
Garbage collection of JS:
|
||||
* JS interpreter automatically collect garbage for memory management.
|
||||
|
||||
OOP of JS:
|
||||
* type themselves define methods for working with values. e.g. `a.sort()`
|
||||
|
||||
Mutable/Immutable of JS:
|
||||
* Primitive types are **immutable**: number, booleans
|
||||
* Object types are **immutable**: change array
|
||||
|
||||
Value convertion of JS:
|
||||
* JS convert values automatically (e.g. from number to string)
|
||||
* Certain rules are there.
|
||||
|
||||
Constant & Variable declaration:
|
||||
* Constant & Variables allow programmer to refer values using names.
|
||||
* Declare constant using `const`
|
||||
* Declare variable using `let` (for new JS), or `var` for old JS version
|
||||
* Constant & Variables are *untyped* (i.e. declaration do no specify type of assigned values)
|
||||
|
||||
## 3.2 Numbers
|
||||
|
||||
Number:
|
||||
* JS's primitive numeric type
|
||||
* Represent *Integers* & *Float*
|
||||
* Using 64-bit floating point format
|
||||
* large as +/- 1.79769x10^308
|
||||
* Small as +/- 5 x 10^-324
|
||||
|
||||
When a number appears directly in JS code, it's **numerical literal**
|
||||
|
||||
### 3.2.1 Integer Literals
|
||||
|
||||
* Base-10 integer: `0`, `3`, `100000`
|
||||
* Hexadecimal (base-16) values: `0xff`, `0xBADCAFE`
|
||||
* Binary (base 2) & Octal (base 8) after ES6: `0b10101`, `0o377`
|
||||
|
||||
### 3.2.2 Floating-Point Literals
|
||||
|
||||
* Traditional notation: `3.14`, `2345.6789`
|
||||
* Exponential notation: `6.02e23` means `6.02 x 10^23`
|
||||
|
||||
#### Separations in numeric literals
|
||||
|
||||
Future JS format will recognize `_` within numeric literals for breaking long literals
|
||||
|
||||
e.g.:
|
||||
* `let billion = 1_000_000_000;`
|
||||
* `let bytes = 0x89_AB_CD_EF;`
|
||||
|
||||
### 3.2.3 Arithmetic in JS
|
||||
|
||||
Basic Arithmetic operators:
|
||||
* addition: `+`
|
||||
* subtraction: `-`
|
||||
* multiplication: `*`
|
||||
* division: `/`
|
||||
* modulo: `%`
|
||||
* exponentiation: `**`
|
||||
|
||||
`Math` object has more complex math operations, check reference for details:
|
||||
* `Math.pow(2,53)`
|
||||
* `Math.round(.6)`
|
||||
* ...
|
||||
|
||||
Note:
|
||||
* Arithmetic in JS do not raise errors for *overflow*/*underflow*/*division by 0*
|
||||
* Overflow (result is larger than largest representable number) -> `Infinity`
|
||||
* Underflow (result is smaller than smallest representable) -> `-Inifinity`
|
||||
* Division by 0 return either `Infinity` or `-Inifinity`
|
||||
* `0/0` return `NaN` (**Not a Number**) as the value is not well-defined
|
||||
* `Infinity/Infinity` return `NaN`
|
||||
|
||||
JS predefined a series of global constants:
|
||||
* `Infinity`
|
||||
* `Number.POSITIVE_INFINITY`
|
||||
* `1/0`
|
||||
* ...
|
||||
check reference for all global constant information
|
||||
|
||||
* `NaN` cannot compare to other value (others can)
|
||||
* Solution to the problem: `x != x` or `Number.isNaN(x)` for comparison
|
||||
|
||||
### 3.2.4 Binary Floating-Point and Rounding Errors
|
||||
|
||||
Real number in real life is continuous & infinite. But due to computer is binary, only finite number of them can be represented by JS floating-point format. Hence, in JS, real number are approximation of the actual number.
|
||||
|
||||
JS us IEEE-754 floating-point representation (a binary representation, that can only represent 1/2, 1/7, 1/1024). Number like `.1` (i.e. `1/10`) can only be approximated
|
||||
|
||||
This problem is generic across computing language using binary representation. Solution include: **manipulate monetary values as integer cents rather than fractional dollars**
|
||||
|
||||
### 3.2.5 Arbitrary Precision Integers with BigInt
|
||||
|
||||
New numeric type **BigInt** (new features of JS) defined in ES2020.
|
||||
|
||||
```js
|
||||
1234n // not-so-big BigInt
|
||||
0b1111n // Binary BigInt
|
||||
0o7777n // Octal BigInt
|
||||
0x800000000n
|
||||
```
|
||||
|
||||
BigInt:
|
||||
* a numeric type for large **(64-bit) integer**
|
||||
* BigInt literals are shown above. (i.e. digits followed by `n`)
|
||||
* Can convert from other number using `BigInt()`
|
||||
|
||||
```js
|
||||
BigInt(Number.MAX_SAFE_INTEGEG) // => 900719925474099n
|
||||
let string = "1" + "0".repeat(100); // 1 followed by 100 zeros
|
||||
BigInt(string)
|
||||
```
|
||||
|
||||
Arithmetic operations with BigInt:
|
||||
|
||||
```js
|
||||
1000n + 2000n
|
||||
3000n - 2000n
|
||||
2000n * 3000n
|
||||
3000n / 997n
|
||||
...
|
||||
```
|
||||
|
||||
### 3.2.6 Dates and Times
|
||||
|
||||
JS has simple Date class, the timestamp count since Jan 1, 1970
|
||||
|
||||
```js
|
||||
let timestamp = Date.now();
|
||||
let now = new Date();
|
||||
let ms = new.getTime(); // milisecond timestamp
|
||||
let iso = now.toISOString(); // Convert to a string in standard format.
|
||||
```
|
||||
|
||||
## 3.3 Text
|
||||
|
||||
* JS use *string* to represent text.
|
||||
* *string* = immutable ordered sequence of 16-bit values.
|
||||
* JS use **zero-based indexing** for string & array. i.e. 1st value start from 0
|
||||
* empty string has length 0
|
||||
|
||||
JS strings & codepoints & characters
|
||||
* JS uses UTF-16 encoding for characters.
|
||||
* Most frequently used characters have 16bit **codepoints**
|
||||
* Some Unicode characters cannot fit in 16bits, may be represented as a sequence of 2 16-bit values (i.e. **surrogate pair**) as shown below
|
||||
|
||||
```js
|
||||
let euro = "€";
|
||||
let love = "❤";
|
||||
euro.length // => 1: this character has one 16-bit element
|
||||
love.length // => 2: UTF-16 encoding of ❤ is "\ud83d\udc99"
|
||||
```
|
||||
|
||||
* Pre ES6, looping through surrogate pair will treat each 16bit as independent value
|
||||
* In ES6, strings are *iterable*, so iterator will recognize these surrogate pairs
|
||||
|
||||
### 3.3.1 String Literals
|
||||
|
||||
Pre ES6, Coding string literals in JS: cover literals within single/double quotes
|
||||
* double/single quotes can be contained within single/double quotes
|
||||
|
||||
```js
|
||||
"" // The empty string: it has zero characters
|
||||
'testing' // single quotes
|
||||
"3.14" // double quotes
|
||||
'name="myform"' // double quotes contained within string delimited by single-quote
|
||||
"Wouldn't you prefer O'Reilly's book?" //
|
||||
"τ is the ratio of a circle's circumference to its radius"
|
||||
```
|
||||
|
||||
In ES6, backticks is added to contain string literals, which allow JS expressions to be embedded within string literals
|
||||
|
||||
```js
|
||||
`"She said 'hi'", he said.`
|
||||
```
|
||||
|
||||
#### multi-line string and new line character sequence
|
||||
|
||||
Pre ES5: JS required string literals to be coded in single line.
|
||||
* Common practice: String literals are broken into multi-lines by concatenated with `+`
|
||||
|
||||
In ES5: JS can break string into multilines by **backslash** `\`
|
||||
```js
|
||||
// A one-line string written on 3 lines:
|
||||
"one\
|
||||
long\
|
||||
line"
|
||||
```
|
||||
|
||||
In ES5: JS can create a two line string written in one line code using **new lien character sequence** `\n`
|
||||
```js
|
||||
// A string representing 2 lines written on one line:
|
||||
'two\nlines'
|
||||
```
|
||||
|
||||
In ES6: backtick allows strings to be broken into multiple lines, while line terminator are part of the string literal:
|
||||
```js
|
||||
// A two-line string written on two lines:
|
||||
`the newline character at the end of this line
|
||||
is included literally in this string`
|
||||
```
|
||||
|
||||
#### JS & HTML mixed up
|
||||
|
||||
JS programming may contain strings of HTML code, while HTML code may contains strings of JS. Both JS & HTML use double/single quote for strings.
|
||||
|
||||
Common practice: use one style of quotes for JS and other style for HTML.
|
||||
|
||||
```html
|
||||
<button onclick="alert('Thank you')">Click Me</button>
|
||||
```
|
||||
* string "Thank you" is single-quoted within a JS expression
|
||||
* JS expression is then double-quoted within HTML event-handler attribute
|
||||
|
||||
### 3.3.2 Escape Sequences in String Literals
|
||||
|
||||
Backslash character `\` combined with specific character = **excape sequence**, which represent a special character
|
||||
|
||||
JS escape sequences
|
||||
| Sequence | Character represented |
|
||||
| -------- | ----------------------------------------------------------------------------------------------------------------------- |
|
||||
| `\0` | NULL (\u0000) |
|
||||
| `\b` | Backspace (\u0008) |
|
||||
| `\t` | Horizontal tab (\u0009) |
|
||||
| `\n` | Newline (\u000A) |
|
||||
| `\v` | Vertical tab (\u000B) |
|
||||
| `\f` | Form feed (\u000C) |
|
||||
| `\r` | Carriage return (\u000D) |
|
||||
| `\"` | Double quote (\u0022) |
|
||||
| `\'` | Apostrophe or single quote (\u0027) |
|
||||
| `\\` | Backslash (\u005C) |
|
||||
| `\xnn` | The Unicode character specified by the two hexadecimal digits nn |
|
||||
| `\unnnn` | The Unicode character specified by the four hexadecimal digits nnnn |
|
||||
| `\u{n}` | The Unicode character specified by the codepoint n, where n is one to six hexadecimal digits between 0 and 10FFFF (ES6) |
|
||||
|
||||
### 3.3.3 Working with Strings
|
||||
|
||||
* concatenate strings (JS' built-in feature) using `+`:
|
||||
```js
|
||||
let msg = "Hello, " + "world"; // Produces the string "Hello, world"
|
||||
let greeting = "Welcome to my blog," + " " + name;
|
||||
```
|
||||
|
||||
* String comparison using `===` (equal) and `!==` (inequal).
|
||||
* Comparison is done by checking 16-bit values
|
||||
* Checking length of a string via length property of the string `.length`
|
||||
|
||||
Other than methods/property mentioned above, JS has rich API (methods):
|
||||
|
||||
```js
|
||||
let s = "Hello, world"; // Start with some text.
|
||||
|
||||
// Obtaining portions of a string
|
||||
s.substring(1,4) // => "ell": the 2nd, 3rd, and 4th characters.
|
||||
s.slice(1,4) // => "ell": same thing
|
||||
s.slice(-3) // => "rld": last 3 characters
|
||||
s.split(", ") // => ["Hello", "world"]: split at delimiter string
|
||||
|
||||
// Searching a string
|
||||
s.indexOf("l") // => 2: position of first letter l
|
||||
s.indexOf("l", 3) // => 3: position of first "l" at or after 3
|
||||
s.indexOf("zz") // => -1: s does not include the substring "zz"
|
||||
s.lastIndexOf("l") // => 10: position of last letter l
|
||||
|
||||
// Boolean searching functions in ES6 and later
|
||||
s.startsWith("Hell") // => true: the string starts with these
|
||||
s.endsWith("!") // => false: s does not end with that
|
||||
s.includes("or") // => true: s includes substring "or"
|
||||
|
||||
// Creating modified versions of a string
|
||||
s.replace("llo", "ya") // => "Heya, world"
|
||||
s.toLowerCase() // => "hello, world"
|
||||
s.toUpperCase() // => "HELLO, WORLD"
|
||||
s.normalize() // Unicode NFC normalization: ES6
|
||||
s.normalize("NFD") // NFD normalization. Also "NFKC", "NFKD"
|
||||
|
||||
// Inspecting individual (16-bit) characters of a string
|
||||
s.charAt(0) // => "H": the first character
|
||||
s.charAt(s.length-1) // => "d": the last character
|
||||
s.charCodeAt(0) // => 72: 16-bit number at the specified position
|
||||
s.codePointAt(0) // => 72: ES6, works for codepoints > 16 bits
|
||||
|
||||
// String padding functions in ES2017
|
||||
"x".padStart(3) // => " x": add spaces on the left to a length of 3
|
||||
"x".padEnd(3) // => "x ": add spaces on the right to a length of 3
|
||||
"x".padStart(3, "*") // => "**x": add stars on the left to a length of 3
|
||||
"x".padEnd(3, "-") // => "x--": add dashes on the right to a length of 3
|
||||
|
||||
// Space trimming functions. trim() is ES5; others ES2019
|
||||
" test ".trim() // => "test": remove spaces at start and end
|
||||
" test ".trimStart() // => "test ": remove spaces on left. Also trimLeft
|
||||
" test ".trimEnd() // => " test": remove spaces at right. Also trimRight
|
||||
|
||||
// Miscellaneous string methods
|
||||
s.concat("!") // => "Hello, world!": just use + operator instead
|
||||
"<>".repeat(5) // => "<><><><><>": concatenate n copies. ES6
|
||||
```
|
||||
|
||||
* strings are immutable in JS. Methods shown above return new strings, instead of modifying original string
|
||||
* strings can be read as array, `s[s.slength-1]` return 2nd last char
|
||||
|
||||
### 3.3.4 Template Literals
|
||||
|
||||
In ES6, backtickes are added:
|
||||
```js
|
||||
let s = `hello world`;
|
||||
```
|
||||
|
||||
**Template literals** = string literal created using backticks
|
||||
* it can include JS expression.
|
||||
* its final value is computed by evaluating expression, convert these values into strings, combining to get result
|
||||
* JS expression: `${ expression }`
|
||||
* Everything outside `${}` is normal string literal text.
|
||||
|
||||
```js
|
||||
let name = "Bill";
|
||||
let greeting = `Hello ${ name }.`; // greeting == "Hello Bill."
|
||||
```
|
||||
|
||||
* Template literal can include multiple expressions.
|
||||
* Use any escape char
|
||||
* Span multi-lines
|
||||
|
||||
```js
|
||||
let errorMessage = `\ // backslash escape the initial newline
|
||||
\u2718 Test failure at ${filename}:${linenumber}:
|
||||
${exception.message}
|
||||
Stack trace:
|
||||
${exception.stack}
|
||||
`;
|
||||
```
|
||||
|
||||
#### Tagged template literals
|
||||
|
||||
**Tagged Template Literals**: Template literals's uncommonly used feature
|
||||
* If a function name (also called "tag function") comes right before the opening backtick, (e.g. shown below)
|
||||
* then the text and values of the expressions within the template literal are passed to the function
|
||||
* And value of this **Tagged Template Literals** is the return value of the function
|
||||
中文翻译:
|
||||
* 如果 function name 在 opening backtick 之前
|
||||
* 那 backtick 以内的文字和值都会被直接传递给 function
|
||||
* 这个方程返回的值就是 **Tagged Template Literals** 的值
|
||||
|
||||
```js
|
||||
`\n`.length // => 1: the string has a single newline character
|
||||
String.raw`\n`.length // => 2: a backslash character and the letter n
|
||||
|
||||
// 这里 `\n` 作为 tagged template literals 被传递给了方程,而导致产生的结果不一样
|
||||
```
|
||||
|
||||
Usage of Tagged Template Literals:
|
||||
* Applying HTML or SQL escaping to the values before substuting them into the text
|
||||
* etc.
|
||||
|
||||
We can define our own template tag function
|
||||
|
||||
### 3.3.5 Pattern Matching
|
||||
|
||||
* **RegExp (Regular Expression)**: a datatype defined by JS.
|
||||
* Used for describing/matching string patterns.
|
||||
* RegExp is not fundamental datatype in JS
|
||||
* Grammer & API of RegExp is complex.
|
||||
|
||||
Grammer of RegExp:
|
||||
* RegExp literal = Text btw a pair of slashes
|
||||
* one or more letter can follow 2nd slash to change meaning of pattern
|
||||
```js
|
||||
/^HTML/; // Match the letters HTML at the start of a string
|
||||
/[1-9][0-9]*/; // Match a nonzero digit, followed by any number of digits
|
||||
/\bjavascript\b/i; // Match a "javascript" as a work, case-sensitive
|
||||
```
|
||||
|
||||
API of RegExp datatype (e.g.):
|
||||
```js
|
||||
let text = "testing: 1, 2, 3"; // Sample text
|
||||
let pattern = /\d+/g; // Matches all instances of one or more digits
|
||||
pattern.test(text) // => true: a match exists
|
||||
text.search(pattern) // => 9: position of first match
|
||||
text.match(pattern) // => ["1", "2", "3"]: array of all matches
|
||||
text.replace(pattern, "#") // => "testing: #, #, #"
|
||||
text.split(/\D+/) // => ["","1","2","3"]: split on nondigits
|
||||
```
|
||||
|
||||
## 3.4 Boolean Values
|
||||
|
||||
* **Boolean values**: evaluated using reserved words `true` & `false`
|
||||
* Comparison in JS:
|
||||
* Equal to: `===`. e.g. `a === 4`
|
||||
* Not-Equal to: `!==`
|
||||
* **Any** JS value can be converted to a boolean value:
|
||||
* Following (i.e. **falsy values**) are converted to false.
|
||||
* All values aren't falsy values are **truthy**
|
||||
```js
|
||||
undefined
|
||||
null
|
||||
0
|
||||
-0
|
||||
NaN
|
||||
"" // the empty string
|
||||
```
|
||||
|
||||
truthy values can be proven as shown:
|
||||
```js
|
||||
if (o!== null)...
|
||||
```
|
||||
|
||||
Methods of Boolean values:
|
||||
* `toString()`: convert `true` to "true".
|
||||
|
||||
3 Important boolean operator:
|
||||
* `&&`: Boolean AND operator. It evaluate (generate) a truthy value iff both operands are truthy
|
||||
* `||`: Boolean OR operator.
|
||||
* `!`: Boolean NOT operator
|
||||
|
||||
```js
|
||||
if ((x === 0 && y === 0) || !(z === 0)) {
|
||||
// x and y are both zero or z is non-zero
|
||||
}
|
||||
```
|
||||
|
||||
## 3.5 null and undefined
|
||||
|
||||
`null`
|
||||
* Def: special value, indicating "absence of a value"
|
||||
* `typeof(null)` return `"object"`; So it means `null` is a special object, with value "no object".
|
||||
* `null` is the sole member of this own type.
|
||||
* It indicate "no value" for data type like number, strings and objects.
|
||||
* similar in other language: `NULL` in C++
|
||||
|
||||
`undefined`
|
||||
* Def: a deeper kind of absence, it's the value of variables that have not been initialized
|
||||
* When query the value of an object project property or array element that **does not exist or not initilized**, return `undefined`
|
||||
* It's predefined global constant, that's initilzed with value `undefined`
|
||||
* `typeof(undefined)` return `"undefined"`, hence it's a special type
|
||||
|
||||
`null` similar as `undefined`
|
||||
* both can use interchangeably.
|
||||
* **equality operator `==`** will evalute them to be equal; **strict equality operator`===`** can distringuish them
|
||||
* Both are falsy values
|
||||
* Both of them have no property/methods
|
||||
* visiting property/methods using `.` or `[]` returns `TypeError`
|
||||
|
||||
`null` different from `undefined` (by author)
|
||||
* `undefined`: a system-level, unexpected or error like absence of value
|
||||
* `null`: program-level, normal, or expected absence of value.
|
||||
* Prefer to be assigned to variable or passed as return
|
||||
|
||||
## 3.6 Symbols
|
||||
|
||||
Prerequisite knowledge: JS's Object type is an unordered collection of properties, each property is a name/value pair.
|
||||
|
||||
Before ES6, property name are strings. Since ES6, **symbols** can also be used as **property name of an object**.
|
||||
|
||||
```js
|
||||
let strname = "string name"; // A string to use as a property name
|
||||
let symname = Symbol("propname"); // A Symbol to use as a property name
|
||||
typeof strname // => "string": strname is a string
|
||||
typeof symname // => "symbol": symname is a symbol
|
||||
let o = {}; // Create a new object
|
||||
o[strname] = 1; // Define a property with a string name
|
||||
o[symname] = 2; // Define a property with a Symbol name
|
||||
o[strname] // => 1: access the string-named property
|
||||
o[symname] // => 2: access the symbol-named property
|
||||
```
|
||||
|
||||
How to obtain a Symbol value:
|
||||
* Symbol type does not have a literal syntax. (e.g. char used for string literal syntax)
|
||||
* Use `Symbol()` function to obtain Symbol value as shown above.
|
||||
* Syntax e.g.: `let variable_name = Symbol("property_name")`
|
||||
|
||||
How to use Symbol value:
|
||||
* Use a symbol value as a property name to add a new property to an object.
|
||||
* `Symbol()` function never return same (symbol) value, even given same string (`"property_name"`). So no worry to overwrite original property in Object.
|
||||
|
||||
Symbol value related functions:
|
||||
* `Symbol()`: used to create symbol value
|
||||
* `s.toString()`: return string used as argument when creating the value
|
||||
* Note: two different symbol value can have same string
|
||||
* `Symbol.for()`: used to search symbol value with given string
|
||||
* JS defines a global Symbol registry
|
||||
* If no Symbol are associated with that string, a new one is created&returned.
|
||||
|
||||
```js
|
||||
let s = Symbol("sym_x");
|
||||
s.toString() // => "Symbol(sym_x)"
|
||||
```
|
||||
|
||||
```js
|
||||
let s = Symbol.for("shared");
|
||||
let t = Symbol.for("shared");
|
||||
s === t // => true
|
||||
s.toString() // => "Symbol(shared)"
|
||||
Symbol.keyFor(t) // => "shared"
|
||||
```
|
||||
|
||||
## 3.7 The Global Object
|
||||
|
||||
## 3.8 Immutable Primitive Values and Mutable Object References
|
||||
|
||||
## 3.9 Type Conversions
|
||||
|
||||
### 3.9.1 Conversions and Equality
|
||||
|
||||
### 3.9.2 Explicit Conversions
|
||||
|
||||
### 3.9.3 Objbect to Primitive Conversions
|
||||
|
||||
## 3.10 Variable Declaration and Assignment
|
||||
|
||||
### 3.10.1 Declarations with `let` and `const`
|
||||
|
||||
### 3.10.2 Variable Declarations with `var`
|
||||
|
||||
### 3.10.3 Destructuring Assignment
|
Loading…
Reference in New Issue