diff --git a/notes/chap12_iterators_and_generators.md b/notes/chap12_iterators_and_generators.md index f249803..c48fd4e 100644 --- a/notes/chap12_iterators_and_generators.md +++ b/notes/chap12_iterators_and_generators.md @@ -1,5 +1,7 @@ # Chapter 12. Iterators and Generators + + ## 12.1 How Iterators Work ## 12.2 Implementing Iterable Objects diff --git a/notes/chap6_objects.md b/notes/chap6_objects.md index d23c8e5..49c4f7b 100644 --- a/notes/chap6_objects.md +++ b/notes/chap6_objects.md @@ -536,6 +536,8 @@ JSON.stringify([point]) // => '["(1, 2)"]' ## 6.10 Extended Object Literal Syntax + + ### 6.10.1 Shorthand Properties ### 6.10.2 Computed Property Names @@ -546,4 +548,29 @@ JSON.stringify([point]) // => '["(1, 2)"]' ### 6.10.5 Shorthand Methods -### 6.10.6 Property Getters and Setters \ No newline at end of file +### 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; } +}; +``` diff --git a/notes/chap8_functions.md b/notes/chap8_functions.md index e14bcbd..f89c47b 100644 --- a/notes/chap8_functions.md +++ b/notes/chap8_functions.md @@ -137,4 +137,116 @@ function hypotenuse(a, 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) \ No newline at end of file +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. \ No newline at end of file