Compare commits

..

No commits in common. "0d0e3e01c1105ebcba98faa44e2a13247ef6513c" and "b4afb10ef26e696ced13c13363f4c907a6bb3cb3" have entirely different histories.

3 changed files with 5 additions and 228 deletions

View File

@ -1,7 +1,5 @@
# Chapter 12. Iterators and Generators
## 12.1 How Iterators Work
## 12.2 Implementing Iterable Objects

View File

@ -536,8 +536,6 @@ JSON.stringify([point]) // => '["(1, 2)"]'
## 6.10 Extended Object Literal Syntax
### 6.10.1 Shorthand Properties
### 6.10.2 Computed Property Names
@ -549,28 +547,3 @@ JSON.stringify([point]) // => '["(1, 2)"]'
### 6.10.5 Shorthand Methods
### 6.10.6 Property Getters and Setters
* All obj properties mentioned above are **data properties**. JS also supports **accessor properties** (
* A accessor property does not have a value, but has 1 or 2 accessor methods: **getter** or **setter**)
How accessor property works:
* When JS program queries value of this accessor property, JS invoke getter method.
* When JS program sets value of the accessor property, JS invokes setter method, and passing value.
R/W property?:
* If a accessor property has both getter & setter, it's a **read/write property**.
* If it only has a getter method, it's a **read-only property**.
* If it only has a setter method, it's a **write-only property**. (not possible with data properties)
* Read it return `undefined`
Accessor property syntax using an extension to object literal syntax:
```js
let o = {
// An ordinary data property
dataProp: value,
// An accessor property defined as a pair of functions.
get accessorProp() { return this.dataProp; },
set accessorProp(value) { this.dataProp = value; }
};
```

View File

@ -20,7 +20,7 @@ JS function definitions can be nested within other functions
### 8.1.1 Function Declarations
**Function declaration (函数声明)** = `function` keyword + Identifier as function name + `(param1, param2, ...)` + `{JS statements as function body}`
**Function declaration** = `function` keyword + Identifier as function name + `(param1, param2, ...)` + `{JS statements as function body}`
* `return` causes function to stop executing and return computed value to caller
* if body has no `return`, value of function is `undefined`
@ -53,200 +53,6 @@ function factorial(x) {
### 8.1.2 Function Expressions
Multiple Function Expression e.g.
```js
// This function expression defines a function that squares its argument.
// Note that we assign it to a variable
const square = function(x) { return x*x; };
// Function expressions can include names, which is useful for recursion.
const f = function fact(x) { if (x <= 1) return 1; else return x*fact(x-1); };
// Function expressions can also be used as arguments to other functions:
[3,2,1].sort(function(a,b) { return a-b; });
// Function expressions are sometimes defined and immediately invoked:
let tensquared = (function(x) {return x*x;}(10));
```
**Function Expression (FE 函数表达式)**:
* FE appear within context of a larger expression, or within statement
* name of function in FE is *optional*. (e.g. 1st FE e.g. has no function name)
* FE/FD declare variable:
* How FD use variable: (follow e.g. in 8.1.1 `function factorial(x)`) declares a variable and assigns a function obj to it.
* How FE use variable: developer can decide whether assign the newly defined function obj to a const or var, so we can refer to it mult-times later. (e.g. 3rd & 5th FE e.g. does not assign function obj to obj, and directly use it)
* Good practice: assign FE to `const` to protect function obj.
**FD vs. FE**:
* Function defined by FD: the func obj are created before the script get executed (i.e. hoisted), so we can call these functions from code that appears above FD.
* Functions defined by FE **DO NOT EXIST** until FE are evaluated.
* To invoke a function (either defined using FE/FD), JS must can refer to it, function defined by FE cannot be referred until it's assigned to a variable
### 8.1.3 Arrow Functions
In ES6, **Arrow Function** provide more compact function syntax. **Use arrow => to separate function parameters from function body**
Syntax of arrow function:
* *general form*: comma-separated list of params in parentheses, followed by `=>` arrow, followed by function body in curly braces
```js
const func_var = (param1, param2) => { return param1 + param2; };
```
* *compact form (single return)*: if function body is a single `return` statement, omit `return`, semicolon, and curly braces
```js
const func_var = (param1, param2) => param1 + param2;
```
* *compact form (1 param)*: if arrow func has only 1 param, omit `()`
```js
const func_var = param => param*param + 2*param;
```
* *compact form (no param)*: if arrow func has no param, `()` must be there
```js
const constantFunc = () => 42;
```
Additional Syntax rules:
* **No newline btw `(param)` and `arrow`**: it will create valid statement with other meaning (e.g. `const polynomial = x`)
* **{} must needed in body for single return statement**: it will avoid syntactic ambiguity:
```js
const f = x => { return { value: x }; }; // Good: f() returns an object
const g = x => ({ value: x }); // Good: g() returns an object
const h = x => { value: x }; // Bad: h() returns nothing
const i = x => { v: x, w: x }; // Bad: Syntax Error
```
#### Where to use arrow function?
It's like lambda function in Python, it's ideal to pass arrow function to another function
```js
// Make a copy of an array with null elements removed.
let filtered = [1,null,2,3].filter(x => x !== null); // filtered == [1,2,3]
```
#### Arrow Func vs other Funcs
* Arrow func inherit value of `this` from the environment (where it's defined)
* Arrow func do not have a `prototype` property, hence it cannot be used as constructor for new classes.
### 8.1.4 Nested Functions
```js
function hypotenuse(a, b) {
function square(x) { return x*x; }
return Math.sqrt(square(a) + square(b));
}
```
Scoping rule of nested function: enclosure function can access param and var of the functions they are nested within (i.e. inner function know outer function's param)
## 8.2 Invoking Functions
JS will not execute function body, when function is defined. Rather executed when func is invoked
5 ways to invoke JS functions:
* As functions
* As methods
* As constructors
* Indirectly through `call()`, `apply()`
* Implicitly
### 8.2.1 Function Invocation
**Invocation Expression**:
```js
func_name(param1, param2);
```
* params can be any argument expression. JS will evaluate these expression and then use result as args.
* For no `return` function, value of return is `undefined`
Use **conditional invocation** on invocation expression: invoke the function only if it's not `null` or `undefined`
```js
f?.(x)
```
equivalent to
```js
(f !== null && f !== undefined) ? (fx) : undefined
```
### 8.2.2 Method Invocation
A **method** = JS function stored in a property of an object.
* **Defining a function method**, given object `o`, method name `m`, and a function `f`:
```js
o.m = f;
```
* **Invoking object method**:
```js
o.m(param1, param2);
```
Method invokation can also use `[]` instead of dot notation:
```js
o["m"](x,y); // Another way to write o.m(x,y).
a[0](z) // Also a method invocation (assuming a[0] is a function).
```
**Invoctaion Context** of invoking by method:
* (OOP) In a method-invocation expression, the object become invocation contaxt, the function body can refer to the object by keyword `this` (e.g. shown below)
```js
let calculator = { // An object literal
operand1: 1,
operand2: 1,
add() { // We're using method shorthand syntax for this function
// Note the use of the this keyword to refer to the containing object.
this.result = this.operand1 + this.operand2;
}
};
calculator.add(); // A method invocation to compute 1+1.
calculator.result // => 2
```
* `this` is a keyword, not a variable or property name.
#### Nested function & `this` keyword
* nested functions do not inherit the this value of the containing function.
* If a nested function is invoked as a method, its this value is the object it was invoked on.
* If a nested function (that is not an arrow function) is invoked as a function, then its this value will be either the global object (non-strict mode) or undefined (strict mode).
* It is a common mistake to assume that a nested function defined within a method and invoked as a function can use this to obtain the invocation context of the method.
Solution (workaround) 1:
```js
let o = { // An object o.
m: function() { // Method m of the object.
let self = this; // Save the "this" value in a variable.
this === o // => true: "this" is the object o.
f(); // Now call the helper function f().
function f() { // A nested function f
this === o // => false: "this" is global or undefined
self === o // => true: self is the outer "this" value.
}
}
};
o.m(); // Invoke the method m on the object o.
```
* Within the method m, we assign the this value to a variable self, and within the nested function f, we can use self instead of this to refer to the containing object.
Solution (workaround) 2 since ES6 **arrow function**:
```js
const f = () => {
this === o // true, since arrow functions inherit this
};
```
* Functions defined as expressions instead of statements are not hoisted, so in order to make this code work, the function definition for f will need to be moved within the method m so that it appears before it is invoked.
Solution (workaround) 3 using `.bind(this)`:
```js
const f = (function() {
this === o // true, since we bound this function to the outer this
}).bind(this);
```
### 8.2.3 Constructor Invocation
**Constructor invocation** = function/method invocation proceded by keyword `new`.
* Constructor invocation differ from regular function and method invocations in arg handling, invocation context, and return value.
* A constructor invocation creates a new, empty object that inherits from the object specified by the prototype property of the constructor.
* Constructor functions are intended to initialize objects, and this newly created object is used as the invocation context, so the constructor function can refer to it with the this keyword.
Function Expression (FE 函数表达式) vs Function Declaration (FD 函数声明):
* FE appear within context of a larger expression
*