From bfd62b902a610aef1e08b28c4af70f5f0634e92d Mon Sep 17 00:00:00 2001 From: Developer Davo Date: Tue, 11 Jun 2019 16:51:04 +0200 Subject: [PATCH 01/13] Update article.md --- 1-js/12-generators-iterators/1-generators/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/12-generators-iterators/1-generators/article.md b/1-js/12-generators-iterators/1-generators/article.md index 93a53777..531d5977 100644 --- a/1-js/12-generators-iterators/1-generators/article.md +++ b/1-js/12-generators-iterators/1-generators/article.md @@ -458,7 +458,7 @@ If we don't catch the error there, then, as usual, it falls through to the outer ## Summary -- Generators are created by generator functions `function*(…) {…}`. +- Generators are created by generator functions `function* f(…) {…}`. - Inside generators (only) there exists a `yield` operator. - The outer code and the generator may exchange results via `next/yield` calls. From ace757d6441377a1e312d228326621ed426c9223 Mon Sep 17 00:00:00 2001 From: DouglasMV <32845487+DouglasMV@users.noreply.github.com> Date: Tue, 11 Jun 2019 14:27:58 -0300 Subject: [PATCH 02/13] missing backticks --- 1-js/05-data-types/03-string/2-check-spam/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/05-data-types/03-string/2-check-spam/task.md b/1-js/05-data-types/03-string/2-check-spam/task.md index 3e722095..98b5dd8a 100644 --- a/1-js/05-data-types/03-string/2-check-spam/task.md +++ b/1-js/05-data-types/03-string/2-check-spam/task.md @@ -4,7 +4,7 @@ importance: 5 # Check for spam -Write a function `checkSpam(str)` that returns `true` if `str` contains 'viagra' or 'XXX', otherwise false. +Write a function `checkSpam(str)` that returns `true` if `str` contains 'viagra' or 'XXX', otherwise `false`. The function must be case-insensitive: From 1856fe3868297c00427c673940bbcdb46935ad4b Mon Sep 17 00:00:00 2001 From: DouglasMV <32845487+DouglasMV@users.noreply.github.com> Date: Tue, 11 Jun 2019 16:36:39 -0300 Subject: [PATCH 03/13] missing backticks --- 1-js/05-data-types/04-array/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/05-data-types/04-array/article.md b/1-js/05-data-types/04-array/article.md index 2d6c225c..c91a9e23 100644 --- a/1-js/05-data-types/04-array/article.md +++ b/1-js/05-data-types/04-array/article.md @@ -453,7 +453,7 @@ We can use an array as a deque with the following operations: - `push(...items)` adds `items` to the end. - `pop()` removes the element from the end and returns it. - `shift()` removes the element from the beginning and returns it. -- `unshift(...items)` adds items to the beginning. +- `unshift(...items)` adds `items` to the beginning. To loop over the elements of the array: - `for (let i=0; i Date: Tue, 11 Jun 2019 17:10:37 -0300 Subject: [PATCH 04/13] typo --- 1-js/05-data-types/04-array/2-create-array/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/05-data-types/04-array/2-create-array/task.md b/1-js/05-data-types/04-array/2-create-array/task.md index 3e930079..16d14071 100644 --- a/1-js/05-data-types/04-array/2-create-array/task.md +++ b/1-js/05-data-types/04-array/2-create-array/task.md @@ -16,7 +16,7 @@ The array in the process: ```js no-beautify Jazz, Blues -Jazz, Bues, Rock-n-Roll +Jazz, Blues, Rock-n-Roll Jazz, Classics, Rock-n-Roll Classics, Rock-n-Roll Rap, Reggae, Classics, Rock-n-Roll From 549845064688caedc1a268af6c6aa17722cfc447 Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Wed, 12 Jun 2019 15:18:51 +0300 Subject: [PATCH 05/13] fixes --- .../07-map-set-weakmap-weakset/article.md | 21 +++- .../08-keys-values-entries/article.md | 95 ++++++++++++++++++- .../01-arraybuffer-binary-arrays/article.md | 18 ++-- .../7-shadow-dom-events/article.md | 12 +-- 4 files changed, 124 insertions(+), 22 deletions(-) diff --git a/1-js/05-data-types/07-map-set-weakmap-weakset/article.md b/1-js/05-data-types/07-map-set-weakmap-weakset/article.md index 8392fff4..0cdf9c8c 100644 --- a/1-js/05-data-types/07-map-set-weakmap-weakset/article.md +++ b/1-js/05-data-types/07-map-set-weakmap-weakset/article.md @@ -58,7 +58,24 @@ alert( visitsCountMap.get(john) ); // 123 Using objects as keys is one of most notable and important `Map` features. For string keys, `Object` can be fine, but it would be difficult to replace the `Map` with a regular `Object` in the example above. -In the old times, before `Map` existed, people added unique identifiers to objects for that: +Let's try: + +```js run +let john = { name: "John" }; + +let visitsCountObj = {}; // try to use an object + +visitsCountObj[john] = 123; // try to use john object as the key + +*!* +// That's what got written! +alert( visitsCountObj["[object Object]"] ); // 123 +*/!* +``` + +As `john` is an object, it got converted to the key string `"[object Object]"`. All objects without a special conversion handling are converted to such string, so they'll all mess up. + +In the old times, before `Map` existed, people used to add unique identifiers to objects for that: ```js run // we add the id field @@ -159,7 +176,7 @@ The iteration goes in the same order as the values were inserted. `Map` preserve Besides that, `Map` has a built-in `forEach` method, similar to `Array`: ```js -// runs the function for each (key, value) pair +// runs the function for each (key, value) pair recipeMap.forEach( (value, key, map) => { alert(`${key}: ${value}`); // cucumber: 500 etc }); diff --git a/1-js/05-data-types/08-keys-values-entries/article.md b/1-js/05-data-types/08-keys-values-entries/article.md index 66ca3ca9..3780b33e 100644 --- a/1-js/05-data-types/08-keys-values-entries/article.md +++ b/1-js/05-data-types/08-keys-values-entries/article.md @@ -1,11 +1,11 @@ # Object.keys, values, entries -Let's step away from the individual data structures and talk about the iterations over them. +Let's step away from the individual data structures and talk about the iterations over them. In the previous chapter we saw methods `map.keys()`, `map.values()`, `map.entries()`. -These methods are generic, there is a common agreement to use them for data structures. If we ever create a data structure of our own, we should implement them too. +These methods are generic, there is a common agreement to use them for data structures. If we ever create a data structure of our own, we should implement them too. They are supported for: @@ -63,8 +63,93 @@ for (let value of Object.values(user)) { } ``` -## Object.keys/values/entries ignore symbolic properties - +```warn header="Object.keys/values/entries ignore symbolic properties" Just like a `for..in` loop, these methods ignore properties that use `Symbol(...)` as keys. -Usually that's convenient. But if we want symbolic keys too, then there's a separate method [Object.getOwnPropertySymbols](mdn:js/Object/getOwnPropertySymbols) that returns an array of only symbolic keys. Also, the method [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) returns *all* keys. +Usually that's convenient. But if we want symbolic keys too, then there's a separate method [Object.getOwnPropertySymbols](mdn:js/Object/getOwnPropertySymbols) that returns an array of only symbolic keys. Also, there exist a method [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys. +``` + +## Object.fromEntries to transform objects + +Sometimes we need to perform a transformation of an object to `Map` and back. + +We already have `new Map(Object.entries(obj))` to make a `Map` from `obj`. + +The syntax of `Object.fromEntries` does the reverse. Given an array of `[key, value]` pairs, it creates an object: + +```js run +let prices = Object.fromEntries([ + ['banana', 1], + ['orange', 2], + ['meat', 4] +]); + +// now prices = { banana: 1, orange: 2, meat: 4 } + +alert(prices.orange); // 2 +``` + +Let's see practical applications. + +For example, we'd like to create a new object with double prices from the existing one. + +For arrays, we have `.map` method that allows to transform an array, but nothing like that for objects. + +So we can use a loop: + +```js run +let prices = { + banana: 1, + orange: 2, + meat: 4, +}; + +let doublePrices = {}; +for(let [product, price] of Object.entries(prices)) { + doublePrices[product] = price * 2; +} + +alert(doublePrices.meat); // 8 +``` + +...Or we can represent the object as an `Array` using `Object.entries`, then perform the operations with `map` (and potentially other array methods), and then go back using `Object.fromEntries`. + +Let's do it for our object: + +```js run +let prices = { + banana: 1, + orange: 2, + meat: 4, +}; + +*!* +let doublePrices = Object.fromEntries( + // convert to array, map, and then fromEntries gives back the object + Object.entries(prices).map(([key, value]) => [key, value * 2]) +); +*/!* + +alert(doublePrices.meat); // 8 +``` + +It may look difficult from the first sight, but becomes easy to understand after you use it once or twice. + +We also can use `fromEntries` to get an object from `Map`. + +E.g. we have a `Map` of prices, but we need to pass it to a 3rd-party code that expects an object. + +Here we go: + +```js run +let map = new Map(); +map.set('banana', 1); +map.set('orange', 2); +map.set('meat', 4); + +let obj = Object.fromEntries(map); + +// now obj = { banana: 1, orange: 2, meat: 4 } + +alert(obj.orange); // 2 +``` diff --git a/4-binary/01-arraybuffer-binary-arrays/article.md b/4-binary/01-arraybuffer-binary-arrays/article.md index de4e719b..9de9ee4d 100644 --- a/4-binary/01-arraybuffer-binary-arrays/article.md +++ b/4-binary/01-arraybuffer-binary-arrays/article.md @@ -99,17 +99,17 @@ new TypedArray(); *!* let arr = new Uint8Array([0, 1, 2, 3]); */!* - alert( arr.length ); // 4 - alert( arr[1] ); // 1 + alert( arr.length ); // 4, created binary array of the same length + alert( arr[1] ); // 1, filled with 4 bytes (unsigned 8-bit integers) with given values ``` -3. If another `TypedArray` is supplied, it does the same: creates a typed array of the same length and copies values. Values are converted to the new type in the process. +3. If another `TypedArray` is supplied, it does the same: creates a typed array of the same length and copies values. Values are converted to the new type in the process, if needed. ```js run let arr16 = new Uint16Array([1, 1000]); *!* let arr8 = new Uint8Array(arr16); */!* alert( arr8[0] ); // 1 - alert( arr8[1] ); // 232 (tried to copy 1000, but can't fit 1000 into 8 bits) + alert( arr8[1] ); // 232, tried to copy 1000, but can't fit 1000 into 8 bits (explanations below) ``` 4. For a numeric argument `length` -- creates the typed array to contain that many elements. Its byte length will be `length` multiplied by the number of bytes in a single item `TypedArray.BYTES_PER_ELEMENT`: @@ -224,6 +224,7 @@ new DataView(buffer, [byteOffset], [byteLength]) For instance, here we extract numbers in different formats from the same buffer: ```js run +// binary array of 4 bytes, all have the maximal value 255 let buffer = new Uint8Array([255, 255, 255, 255]).buffer; let dataView = new DataView(buffer); @@ -231,13 +232,13 @@ let dataView = new DataView(buffer); // get 8-bit number at offset 0 alert( dataView.getUint8(0) ); // 255 -// now get 16-bit number at offset 0, that's 2 bytes, both with max value +// now get 16-bit number at offset 0, it consists of 2 bytes, together iterpreted as 65535 alert( dataView.getUint16(0) ); // 65535 (biggest 16-bit unsigned int) // get 32-bit number at offset 0 alert( dataView.getUint32(0) ); // 4294967295 (biggest 32-bit unsigned int) -dataView.setUint32(0, 0); // set 4-byte number to zero +dataView.setUint32(0, 0); // set 4-byte number to zero, thus setting all bytes to 0 ``` `DataView` is great when we store mixed-format data in the same buffer. E.g we store a sequence of pairs (16-bit integer, 32-bit float). Then `DataView` allows to access them easily. @@ -257,12 +258,11 @@ To do almost any operation on `ArrayBuffer`, we need a view. In most cases we create and operate directly on typed arrays, leaving `ArrayBuffer` under cover, as a "common discriminator". We can access it as `.buffer` and make another view if needed. -There are also two additional terms: +There are also two additional terms, that are used in descriptions of methods that operate on binary data: - `ArrayBufferView` is an umbrella term for all these kinds of views. - `BufferSource` is an umbrella term for `ArrayBuffer` or `ArrayBufferView`. -These are used in descriptions of methods that operate on binary data. `BufferSource` is one of the most common terms, as it means "any kind of binary data" -- an `ArrayBuffer` or a view over it. - +We'll see these terms in the next chapters. `BufferSource` is one of the most common terms, as it means "any kind of binary data" -- an `ArrayBuffer` or a view over it. Here's a cheatsheet: diff --git a/8-web-components/7-shadow-dom-events/article.md b/8-web-components/7-shadow-dom-events/article.md index 14e310a5..4199d104 100644 --- a/8-web-components/7-shadow-dom-events/article.md +++ b/8-web-components/7-shadow-dom-events/article.md @@ -2,9 +2,9 @@ The idea behind shadow tree is to encapsulate internal implementation details of a component. -Let's say, a click event happens inside a shadow DOM of `` component. But scripts in the main document have no idea about the shadow DOM internals, especially if the component comes from a 3rd-party library or so. +Let's say, a click event happens inside a shadow DOM of `` component. But scripts in the main document have no idea about the shadow DOM internals, especially if the component comes from a 3rd-party library. -So, to keep things simple, the browser *retargets* the event. +So, to keep the details encapsulated, the browser *retargets* the event. **Events that happen in shadow DOM have the host element as the target, when caught outside of the component.** @@ -39,7 +39,7 @@ Event retargeting is a great thing to have, because the outer document doesn't h **Retargeting does not occur if the event occurs on a slotted element, that physically lives in the light DOM.** -For example, if a user clicks on `` in the example below, the event target is exactly this element, for both shadow and light handlers: +For example, if a user clicks on `` in the example below, the event target is exactly this `span` element, for both shadow and light handlers: ```html run autorun="no-epub" untrusted height=60 @@ -75,7 +75,7 @@ For purposes of event bubbling, flattened DOM is used. So, if we have a slotted element, and an event occurs somewhere inside it, then it bubbles up to the `` and upwards. -The full path to the original event target, with all the shadow root elements, can be obtained using `event.composedPath()`. As we can see from the name of the method, that path is taken after the composition. +The full path to the original event target, with all the shadow elements, can be obtained using `event.composedPath()`. As we can see from the name of the method, that path is taken after the composition. In the example above, the flattened DOM is: @@ -119,7 +119,7 @@ All touch events and pointer events also have `composed: true`. There are some events that have `composed: false` though: -- `mouseenter`, `mouseleave` (they also do not bubble), +- `mouseenter`, `mouseleave` (they do not bubble at all), - `load`, `unload`, `abort`, `error`, - `select`, - `slotchange`. @@ -189,4 +189,4 @@ These events can be caught only on elements within the same DOM. If we dispatch a `CustomEvent`, then we should explicitly set `composed: true`. -Please note that in case of nested components, composed events bubble through all shadow DOM boundaries. So, if an event is intended only for the immediate enclosing component, we can also dispatch it on the shadow host. Then it's out of the shadow DOM already. +Please note that in case of nested components, one shadow DOM may be nested into another. In that case composed events bubble through all shadow DOM boundaries. So, if an event is intended only for the immediate enclosing component, we can also dispatch it on the shadow host and set `composed: false`. Then it's out of the component shadow DOM, but won't bubble up to higher-level DOM. From 60585f2cb825e366dab1e8d8202e278ff85d840f Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Wed, 12 Jun 2019 15:47:13 +0300 Subject: [PATCH 06/13] fix --- 1-js/05-data-types/07-map-set-weakmap-weakset/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/05-data-types/07-map-set-weakmap-weakset/article.md b/1-js/05-data-types/07-map-set-weakmap-weakset/article.md index 0cdf9c8c..47658833 100644 --- a/1-js/05-data-types/07-map-set-weakmap-weakset/article.md +++ b/1-js/05-data-types/07-map-set-weakmap-weakset/article.md @@ -189,7 +189,7 @@ A `Set` is a collection of values, where each value may occur only once. Its main methods are: -- `new Set(iterable)` -- creates the set, optionally from an array of values (any iterable will do). +- `new Set(iterable)` -- creates the set, and if an `iterable` object is provided (usually an array), copies values from it into the set. - `set.add(value)` -- adds a value, returns the set itself. - `set.delete(value)` -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. - `set.has(value)` -- returns `true` if the value exists in the set, otherwise `false`. From 852b9bf581cfcdc18088e3c9ec1c3891af7b2e04 Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Wed, 12 Jun 2019 22:37:45 +0300 Subject: [PATCH 07/13] proxy --- .../super-homeobject-wrong.png | Bin 10763 -> 9782 bytes .../super-homeobject-wrong@2x.png | Bin 0 -> 23046 bytes .../01-proxy/01-error-nonexisting/solution.md | 23 + 10-misc/01-proxy/01-error-nonexisting/task.md | 31 + .../01-proxy/02-array-negative/solution.md | 19 + 10-misc/01-proxy/02-array-negative/task.md | 33 + 10-misc/01-proxy/03-observable/solution.md | 40 + 10-misc/01-proxy/03-observable/task.md | 29 + 10-misc/01-proxy/article.md | 877 ++++++++++++++++++ 10-misc/01-proxy/proxy-inherit.png | Bin 0 -> 17381 bytes 10-misc/01-proxy/proxy-inherit@2x.png | Bin 0 -> 40525 bytes 10-misc/01-proxy/proxy.png | Bin 0 -> 12488 bytes 10-misc/01-proxy/proxy@2x.png | Bin 0 -> 29309 bytes .../build-tree-dom.view/index.html | 2 +- .../innerhtml.view/index.html | 2 +- .../source.view/index.html | 4 +- .../7-create-object-tree/task.md | 2 +- .../07-modifying-document/article.md | 24 +- .../5-keyboard-events/article.md | 8 +- figures.sketch | Bin 5364891 -> 5293931 bytes 20 files changed, 1074 insertions(+), 20 deletions(-) create mode 100644 1-js/09-classes/02-class-inheritance/super-homeobject-wrong@2x.png create mode 100644 10-misc/01-proxy/01-error-nonexisting/solution.md create mode 100644 10-misc/01-proxy/01-error-nonexisting/task.md create mode 100644 10-misc/01-proxy/02-array-negative/solution.md create mode 100644 10-misc/01-proxy/02-array-negative/task.md create mode 100644 10-misc/01-proxy/03-observable/solution.md create mode 100644 10-misc/01-proxy/03-observable/task.md create mode 100644 10-misc/01-proxy/article.md create mode 100644 10-misc/01-proxy/proxy-inherit.png create mode 100644 10-misc/01-proxy/proxy-inherit@2x.png create mode 100644 10-misc/01-proxy/proxy.png create mode 100644 10-misc/01-proxy/proxy@2x.png diff --git a/1-js/09-classes/02-class-inheritance/super-homeobject-wrong.png b/1-js/09-classes/02-class-inheritance/super-homeobject-wrong.png index b1871dc722e0e39ec8b7bfc82bc22029a5900440..30f4d9128fdc9c09f45005240a20218feafa105a 100644 GIT binary patch literal 9782 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 diff --git a/1-js/09-classes/02-class-inheritance/super-homeobject-wrong@2x.png b/1-js/09-classes/02-class-inheritance/super-homeobject-wrong@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e7fd103f4bb10a96b9c58c4e231f71f10f0a5204 GIT binary patch literal 23046 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 literal 0 HcmV?d00001 diff --git a/10-misc/01-proxy/01-error-nonexisting/solution.md b/10-misc/01-proxy/01-error-nonexisting/solution.md new file mode 100644 index 00000000..099664a1 --- /dev/null +++ b/10-misc/01-proxy/01-error-nonexisting/solution.md @@ -0,0 +1,23 @@ + +```js run +let user = { + name: "John" +}; + +function wrap(target) { + return new Proxy(target, { + get(target, prop, receiver) { + if (prop in target) { + return Reflect.get(target, prop, receiver); + } else { + throw new ReferenceError(`Property doesn't exist: "${prop}"`) + } + } + }); +} + +user = wrap(user); + +alert(user.name); // John +alert(user.age); // Error: Property doesn't exist +``` diff --git a/10-misc/01-proxy/01-error-nonexisting/task.md b/10-misc/01-proxy/01-error-nonexisting/task.md new file mode 100644 index 00000000..0b8b3572 --- /dev/null +++ b/10-misc/01-proxy/01-error-nonexisting/task.md @@ -0,0 +1,31 @@ + +# Error on reading non-existant property + +Create a proxy that throws an error for an attempt to read of a non-existant property. + +That can help to detect programming mistakes early. + +Write a function `wrap(target)` that takes an object `target` and return a proxy instead with that functionality. + +That's how it should work: + +```js +let user = { + name: "John" +}; + +function wrap(target) { + return new Proxy(target, { +*!* + /* your code */ +*/!* + }); +} + +user = wrap(user); + +alert(user.name); // John +*!* +alert(user.age); // Error: Property doesn't exist +*/!* +``` diff --git a/10-misc/01-proxy/02-array-negative/solution.md b/10-misc/01-proxy/02-array-negative/solution.md new file mode 100644 index 00000000..20720550 --- /dev/null +++ b/10-misc/01-proxy/02-array-negative/solution.md @@ -0,0 +1,19 @@ + +```js run +let array = [1, 2, 3]; + +array = new Proxy(array, { + get(target, prop, receiver) { + if (prop < 0) { + // even if we access it like arr[1] + // prop is a string, so need to convert it to number + prop = +prop + target.length; + } + return Reflect.get(target, prop, receiver); + } +}); + + +alert(array[-1]); // 3 +alert(array[-2]); // 2 +``` diff --git a/10-misc/01-proxy/02-array-negative/task.md b/10-misc/01-proxy/02-array-negative/task.md new file mode 100644 index 00000000..6663b6f5 --- /dev/null +++ b/10-misc/01-proxy/02-array-negative/task.md @@ -0,0 +1,33 @@ + +# Accessing array[-1] + +In some languages, we can access array elements using negative indexes, counted from the end. + +Like this: + +```js +let array = [1, 2, 3]; + +array[-1]; // 3, the last element +array[-2]; // 2, one step from the end +array[-3]; // 1, two steps from the end +``` + +In other words, `array[-N]` is the same as `array[array.length - N]`. + +Create a proxy to implement that behavior. + +That's how it should work: + +```js +let array = [1, 2, 3]; + +array = new Proxy(array, { + /* your code */ +}); + +alert( array[-1] ); // 3 +alert( array[-2] ); // 2 + +// Other array functionality should be kept "as is" +``` diff --git a/10-misc/01-proxy/03-observable/solution.md b/10-misc/01-proxy/03-observable/solution.md new file mode 100644 index 00000000..dcb4f2a7 --- /dev/null +++ b/10-misc/01-proxy/03-observable/solution.md @@ -0,0 +1,40 @@ +The solution consists of two parts: + +1. Whenever `.observe(handler)` is called, we need to remember the handler somewhere, to be able to call it later. We can store it right in the object, using our symbol as the key. +2. We need a proxy with `set` trap to call handlers in case of any change. + +```js run +let handlers = Symbol('handlers'); + +function makeObservable(target) { + // 1. Initialize handlers store + target[handlers] = []; + + // Store the handler function in array for future calls + target.observe = function(handler) { + this[handlers].push(handler); + }; + + // 2. Create a proxy to handle changes + return new Proxy(target, { + set(target, property, value, receiver) { + let success = Reflect.set(...arguments); // forward the operation to object + if (success) { // if there were no error while setting the property + // call all handlers + target[handlers].forEach(handler => handler(property, value)); + } + return success; + } + }); +} + +let user = {}; + +user = makeObservable(user); + +user.observe((key, value) => { + alert(`SET ${key}=${value}`); +}); + +user.name = "John"; +``` diff --git a/10-misc/01-proxy/03-observable/task.md b/10-misc/01-proxy/03-observable/task.md new file mode 100644 index 00000000..6220104c --- /dev/null +++ b/10-misc/01-proxy/03-observable/task.md @@ -0,0 +1,29 @@ + +# Observable + +Create a function `makeObservable(target)` that "makes the object observable" by returning a proxy. + +Here's how it should work: + +```js run +function makeObservable(target) { + /* your code */ +} + +let user = {}; +user = makeObservable(user); + +user.observe((key, value) => { + alert(`SET ${key}=${value}`); +}); + +user.name = "John"; // alerts: SET name=John +``` + +In other words, an object returned by `makeObservable` has the method `observe(handler)`. + +Whenever a property changes, `handler(key, value)` is called with the name and value o the property. + + +P.S. In this task, please handle only writing to a property. Other operations can be implemented in a similar way. +P.P.S. You might want to introduce a global variable or a global structure to store handlers. That's fine here. In real life, such function lives in a module, that has its own global scope. diff --git a/10-misc/01-proxy/article.md b/10-misc/01-proxy/article.md new file mode 100644 index 00000000..63b4ca2f --- /dev/null +++ b/10-misc/01-proxy/article.md @@ -0,0 +1,877 @@ + +# Proxy and Reflect + +A *proxy* wraps another object and intercepts operations, like reading/writing properties and others, optionally handling them on its own, or transparently allowing the object to handle them. + +Proxies are used in many libraries and some browser frameworks. We'll see many practical applications in this chapter. + +The syntax: + +```js +let proxy = new Proxy(target, handler) +``` + +- `target` -- is an object to wrap, can be anything, including functions. +- `handler` -- an object with "traps": methods that intercept operations., e.g. `get` for reading a property, `set` for writing a property, etc. + +For operations on `proxy`, if there's a corresponding trap in `handler`, then it runs, and the proxy has a chance to handle it, otherwise the operation is performed on `target`. + +As a starting example, let's create a proxy without any traps: + +```js run +let target = {}; +let proxy = new Proxy(target, {}); // empty handler + +proxy.test = 5; // writing to proxy (1) +alert(target.test); // 5, the property appeared in target! + +alert(proxy.test); // 5, we can read it from proxy too (2) + +for(let key in proxy) alert(key); // test, iteration works (3) +``` + +As there are no traps, all operations on `proxy` are forwarded to `target`. + +1. A writing operation `proxy.test=` sets the value on `target`. +2. A reading operation `proxy.test` returns the value from `target`. +3. Iteration over `proxy` returns values from `target`. + +As we can see, without any traps, `proxy` is a transparent wrapper around `target`. + +![](proxy.png) + +The proxy is a special "exotic object". It doesn't have "own" properties. With an empty handler it transparently forwards operations to `target`. + +If we want any magic, we should add traps. + +There's a list of internal object operations in the [Proxy specification](https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots). A proxy can intercept any of these, we just need to add a handler method. + +In the table below: +- **Internal Method** is the specification-specific name for the operation. For example, `[[Get]]` is the name of the internal, specification-only method of reading a property. The specification describes how this is done at the very lowest level. +- **Handler Method** is a method name that we should add to proxy `handler` to trap the operation and perform custom actions. + + +| Internal Method | Handler Method | Traps... | +|-----------------|----------------|-------------| +| `[[Get]]` | `get` | reading a property | +| `[[Set]]` | `set` | writing to a property | +| `[[HasProperty]]` | `has` | `in` operator | +| `[[Delete]]` | `deleteProperty` | `delete` operator | +| `[[Call]]` | `apply` | function call | +| `[[Construct]]` | `construct` | `new` operator | +| `[[GetPrototypeOf]]` | `getPrototypeOf` | [Object.getPrototypeOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf) | +| `[[SetPrototypeOf]]` | `setPrototypeOf` | [Object.setPrototypeOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf) | +| `[[IsExtensible]]` | `isExtensible` | [Object.isExtensible](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible) | +| `[[PreventExtensions]]` | `preventExtensions` | [Object.preventExtensions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions) | +| `[[GetOwnProperty]]` | `getOwnPropertyDescriptor` | [Object.getOwnPropertyDescriptor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor) | +| `[[DefineOwnProperty]]` | `defineProperty` | [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty), [Object.defineProperties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties) | +| `[[OwnPropertyKeys]]` | `ownKeys` | [Object.keys](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys), [Object.getOwnPropertyNames](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames), [Object.getOwnPropertySymbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols), iteration keys | + +```warn header="Invariants" +JavaScript enforces some invariants -- conditions that must be fulfilled by internal methods and traps. + +Most of them are for return values: +- `[[Set]]` must return `true` if the value was written successfully, otherwise `false`. +- `[[Delete]]` must return `true` if the value was deleted successfully, otherwise `false`. +- ...and so on, we'll see more in examples below. + +There are some other invariants, like: +- `[[GetPrototypeOf]]`, applied to the proxy object must return the same value as `[[GetPrototypeOf]]` applied to the proxy object's target object. + +In other words, reading prototype of a `proxy` must always return the prototype of the target object. The `getPrototypeOf` trap may intercept this operation, but it must follow this rule, not do something crazy. + +Invariants ensure correct and consistent behavior of language features. The full invariants list is in [the specification](https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots), you probably won't violate them, if not doing something weird. +``` + +Let's see how that works on practical examples. + +## Default value with "get" trap + +The most common traps are for reading/writing properties. + +To intercept the reading, the `handler` should have a method `get(target, property, receiver)`. + +It triggers when a property is read: + +- `target` -- is the target object, the one passed as the first argument to `new Proxy`, +- `property` -- property name, +- `receiver` -- if the property is a getter, then `receiver` is the object that's going to be used as `this` in that code. Usually that's the `proxy` object itself (or an object that inherits from it, if we inherit from proxy). + +Let's use `get` to implement default values for an object. + +For instance, we'd like a numeric array to return `0` for non-existant values instead of `undefined`. + +Let's wrap it into a proxy that traps reading and returns the default value if there's no such property: + +```js run +let numbers = [0, 1, 2]; + +numbers = new Proxy(numbers, { + get(target, prop) { + if (prop in target) { + return target[prop]; + } else { + return 0; // default value + } + } +}); + +*!* +alert( numbers[1] ); // 1 +alert( numbers[123] ); // 0 (no such value) +*/!* +``` + +The approach is generic. We can use `Proxy` to implement any logic for "default" values. + +Imagine, we have a dictionary with phrases along with translations: + +```js run +let dictionary = { + 'Hello': 'Hola', + 'Bye': 'Adiós' +}; + +alert( dictionary['Hello'] ); // Hola +alert( dictionary['Welcome'] ); // undefined +``` + +Right now, if there's no phrase, reading from `dictionary` returns `undefined`. But in practice, leaving a phrase non-translated is usually better than `undefined`. So let's make a non-translated phrase the default value instead of `undefined`. + +To achieve that, we'll wrap `dictionary` in a proxy that intercepts reading operations: + +```js run +let dictionary = { + 'Hello': 'Hola', + 'Bye': 'Adiós' +}; + +dictionary = new Proxy(dictionary, { +*!* + get(target, phrase) { // intercept reading a property from dictionary +*/!* + if (phrase in target) { // if we have it in the dictionary + return target[phrase]; // return the translation + } else { + // otherwise, return the non-translated phrase + return phrase; + } + } +}); + +// Look up arbitrary phrases in the dictionary! +// At worst, they are not translated. +alert( dictionary['Hello'] ); // Hola +*!* +alert( dictionary['Welcome to Proxy']); // Welcome to Proxy (no translation) +*/!* +``` + +````smart header="Proxy should be used instead of `target` everywhere" +Please note how the proxy overwrites the variable: + +```js +dictionary = new Proxy(dictionary, ...); +numbers = new Proxy(numbers, ...); +``` + +The proxy should totally replace the target object everywhere. No one should ever reference the target object after it got proxied. Otherwise it's easy to mess up. +```` + +## Validation with "set" trap + +Now let's intercept writing as well. + +Let's say we want a numeric array. If a value of another type is added, there should be an error. + +The `set` trap triggers when a property is written: `set(target, property, value, receiver)` + +- `target` -- is the target object, the one passed as the first argument to `new Proxy`, +- `property` -- property name, +- `value` -- property value, +- `receiver` -- same as in `get` trap, only matters if the property is a setter. + +The `set` trap should return `true` if setting is successful, and `false` otherwise (leads to `TypeError`). + +Let's use it to validate new values: + +```js run +let numbers = []; + +numbers = new Proxy(numbers, { // (*) +*!* + set(target, prop, val) { // to intercept property writing +*/!* + if (typeof val == 'number') { + target[prop] = val; + return true; + } else { + return false; + } + } +}); + +numbers.push(1); +numbers.push(2); +alert("Length is: " + numbers.length); // 2 + +*!* +numbers.push("test"); // TypeError ('set' on proxy returned false) +*/!* + +alert("This line is never reached (error in the line above)"); +``` + +Please note: the built-in functionality of arrays is still working! The `length` property auto-increases when values are added. Our proxy doesn't break anything. + +Also, we don't have to override value-adding array methods like `push` and `unshift`, and so on! Internally, they use `[[Set]]` operation, that's intercepted by the proxy. + +So the code is clean and concise. + +```warn header="Don't forget to return `true`" +As said above, there are invariants to be held. + +For `set`, it must return `true` for a successful write. + +If it returns a falsy value (or doesn't return anything), that triggers `TypeError`. +``` + +## Protected properties with "deleteProperty" and "ownKeys" + +There's a widespread convention that properties and methods prefixed by an underscore `_` are internal. They shouldn't be accessible from outside the object. + +Technically, that's possible though: + +```js run +let user = { + name: "John", + _password: "secret" +}; + +alert(user._password); // secret +``` + +Let's use proxies to prevent any access to properties starting with `_`. + +We'll need the traps: +- `get` to throw an error when reading, +- `set` to throw an error when writing, +- `deleteProperty` to throw an error when deleting, +- `ownKeys` to skip properties starting with `_` when iterating over an object or using `Object.keys()` + +Here's the code: + +```js run +let user = { + name: "John", + _password: "***" +}; + +user = new Proxy(user, { +*!* + get(target, prop) { +*/!* + if (prop.startsWith('_')) { + throw new Error("Access denied"); + } + let value = target[prop]; + return (typeof value === 'function') ? value.bind(target) : value; // (*) + }, +*!* + set(target, prop, val) { // to intercept property writing +*/!* + if (prop.startsWith('_')) { + throw new Error("Access denied"); + } else { + target[prop] = val; + } + }, +*!* + deleteProperty(target, prop) { // to intercept property deletion +*/!* + if (prop.startsWith('_')) { + throw new Error("Access denied"); + } else { + delete target[prop]; + return true; + } + }, +*!* + ownKeys(target) { // to intercept property list +*/!* + return Object.keys(target).filter(key => !key.startsWith('_')); + } +}); + +// "get" doesn't allow to read _password +try { + alert(user._password); // Error: Access denied +} catch(e) { alert(e.message); } + +// "set" doesn't allow to write _password +try { + user._password = "test"; // Error: Access denied +} catch(e) { alert(e.message); } + +// "deleteProperty" doesn't allow to delete _password +try { + delete user._password; // Error: Access denied +} catch(e) { alert(e.message); } + +// "ownKeys" filters out _password +for(let key in user) alert(key); // name +``` + +Please note the important detail in `get` trap, in the line `(*)`: + +```js +get(target, prop) { + // ... + let value = target[prop]; +*!* + return (typeof value === 'function') ? value.bind(target) : value; // (*) +*/!* +} +``` + +If an object method is called, such as `user.checkPassword()`, it must be able to access `_password`: + +```js +user = { + // ... + checkPassword(value) { + // object method must be able to read _password + return value === this._password; + } +} +``` + +Normally, `user.checkPassword()` call gets proxied `user` as `this` (the object before dot becomes `this`), so when it tries to access `this._password`, the property protection kicks in and throws an error. So we bind it to `target` in the line `(*)`. Then all operations from that function directly reference the object, without any property protection. + +That solution is not ideal, as the method may pass the unproxied object somewhere else, and then we'll get messed up: where's the original object, and where's the proxied one. + +As an object may be proxied multiple times (multiple proxies may add different "tweaks" to the object), weird bugs may follow. + +So, for complex objects with methods such proxy shouldn't be used. + +```smart header="Private properties of a class" +Modern JavaScript engines natively support private properties in classes, prefixed with `#`. They are described in the chapter . No proxies required. + +Such properties have their own issues though. In particular, they are not inherited. +``` + + +## "In range" with "has" trap + +Let's say we have a range object: + +```js +let range = { + start: 1, + end: 10 +}; +``` + +We'd like to use "in" operator to check that a number is in `range`. + +The "has" trap intercepts "in" calls: `has(target, property)` + +- `target` -- is the target object, passed as the first argument to `new Proxy`, +- `property` -- property name + +Here's the demo: + +```js run +let range = { + start: 1, + end: 10 +}; + +range = new Proxy(range, { +*!* + has(target, prop) { +*/!* + return prop >= target.start && prop <= target.end + } +}); + +*!* +alert(5 in range); // true +alert(50 in range); // false +*/!* +``` + +A nice syntactic sugar, isn't it? + +## Wrapping functions: "apply" + +We can wrap a proxy around a function as well. + +The `apply(target, thisArg, args)` trap handles calling a proxy as function: + +- `target` is the target object, +- `thisArg` is the value of `this`. +- `args` is a list of arguments. + +For example, let's recall `delay(f, ms)` decorator, that we did in the chapter . + +In that chapter we did it without proxies. A call to `delay(f, ms)` would return a function that forwards all calls to `f` after `ms` milliseconds. + +Here's the function-based implementation: + +```js run +// no proxies, just a function wrapper +function delay(f, ms) { + // return a wrapper that passes the call to f after the timeout + return function() { // (*) + setTimeout(() => f.apply(this, arguments), ms); + }; +} + +function sayHi(user) { + alert(`Hello, ${user}!`); +} + +// now calls to sayHi will be delayed for 3 seconds +sayHi = delay(sayHi, 3000); + +sayHi("John"); // Hello, John! (after 3 seconds) +``` + +As you can see, that mostly works. The wrapper function `(*)` performs the call after the timeout. + +But a wrapper function does not forward property read/write operations or anything else. So if we have a property on the original function, we can't access it after wrapping: + +```js run +function delay(f, ms) { + return function() { + setTimeout(() => f.apply(this, arguments), ms); + }; +} + +function sayHi(user) { + alert(`Hello, ${user}!`); +} + +*!* +alert(sayHi.length); // 1 (function length is the arguments count) +*/!* + +sayHi = delay(sayHi, 3000); + +*!* +alert(sayHi.length); // 0 (wrapper has no arguments) +*/!* +``` + + +`Proxy` is much more powerful, as it forwards everything to the target object. + +Let's use `Proxy` instead of a wrapping function: + +```js run +function delay(f, ms) { + return new Proxy(f, { + apply(target, thisArg, args) { + setTimeout(() => target.apply(thisArg, args), ms); + } + }); +} + +function sayHi(user) { + alert(`Hello, ${user}!`); +} + +sayHi = delay(sayHi, 3000); + +*!* +alert(sayHi.length); // 1 (*) proxy forwards "get length" operation to the target +*/!* + +sayHi("John"); // Hello, John! (after 3 seconds) +``` + +The result is the same, but now not only calls, but all operations on the proxy are forwarded to the original function. So `sayHi.length` is returned correctly after the wrapping in the line `(*)`. + +We've got a "richer" wrapper. + +There exist other traps, but probably you've already got the idea. + +## Reflect + +The `Reflect` API was designed to work in tandem with `Proxy`. + +For every internal object operation that can be trapped, there's a `Reflect` method. It has the same name and arguments as the trap, and can be used to forward the operation to an object. + +For example: + +```js run +let user = { + name: "John", +}; + +user = new Proxy(user, { + get(target, prop, receiver) { + alert(`GET ${prop}`); +*!* + return Reflect.get(target, prop, receiver); // (1) +*/!* + }, + set(target, prop, val, receiver) { + alert(`SET ${prop} TO ${val}`); +*!* + return Reflect.set(target, prop, val, receiver); // (2) +*/!* + } +}); + +let name = user.name; // GET name +user.name = "Pete"; // SET name TO Pete +``` + +- `Reflect.get` gets the property, like `target[prop]` that we used before. +- `Reflect.set` sets the property, like `target[prop] = value`, and also ensures the correct return value. + +In most cases, we can do the same thing without `Reflect`. But we may miss some peculiar aspects. + +Consider the following example, it doesn't use `Reflect` and doesn't work right. + +We have a proxied user object and inherit from it, then use a getter: + +```js run +let user = { + _name: "Guest", + get name() { + return this._name; + } +}; + +user = new Proxy(user, { + get(target, prop, receiver) { + return target[prop]; // (*) + } +}); + + +let admin = { + __proto__: user, + _name: "Admin" +}; + +*!* +// Expected: Admin +alert(admin.name); // Guest (?!?) +*/!* +``` + +As you can see, the result is incorrect! The `admin.name` is expected to be `"Admin"`, not `"Guest"`! Without the proxy, it would be `"Admin"`, looks like the proxying "broke" our object. + +![](proxy-inherit.png) + +Why this happens? That's easy to understand if we explore what's going on during the call in the last line of the code. + +1. There's no `name` property in `admin`, so `admin.name` call goes to `admin` prototype. +2. The prototype is the proxy, so its `get` trap intercepts the attempt to read `name`. +3. In the line `(*)` it returns `target[prop]`, but what is the `target`? + - The `target`, the first argument of `get`, is always the object passed to `new Proxy`, the original `user`. + - So, `target[prop]` invokes the getter `name` with `this=target=user`. + - Hence the result is `"Guest"`. + +How to fix it? That's what the `receiver`, the third argument of `get` is for! It holds the correct `this`. We just need to call `Reflect.get` to pass it on. + +Here's the correct variant: + +```js run +let user = { + _name: "Guest", + get name() { + return this._name; + } +}; + +user = new Proxy(user, { + get(target, prop, receiver) { +*!* + return Reflect.get(target, prop, receiver); // (*) +*/!* + } +}); + + +let admin = { + __proto__: user, + _name: "Admin" +}; + +*!* +alert(admin.name); // Admin +*/!* +``` + +Now the `receiver` holding the correct `this` is passed to getter by `Reflect.get` in the line `(*)`, so it works correctly. + +We could also write the trap as: + +```js +get(target, prop, receiver) { + return Reflect.get(*!*...arguments*/!*); +} +``` + +`Reflect` calls are named exactly the same way as traps and accept the same arguments. They were specifically designed this way. + +So, `return Reflect...` provides a safe no-brainer to forward the operation and make sure we don't forget anything related to that. + +## Proxy limitations + +Proxies are a great way to alter or tweak the behavior of the existing objects, including built-in ones, such as arrays. + +Still, it's not perfect. There are limitations. + +### Built-in objects: Internal slots + +Many built-in objects, for example `Map`, `Set`, `Date`, `Promise` and others make use of so-called "internal slots". + +These are like properties, but reserved for internal purposes. Built-in methods access them directly, not via `[[Get]]/[[Set]]` internal methods. So `Proxy` can't intercept that. + +Who cares? They are internal anyway! + +Well, here's the issue. After such built-in object gets proxied, the proxy doesn't have these internal slots, so built-in methods will fail. + +For example: + +```js run +let map = new Map(); + +let proxy = new Proxy(map, {}); + +*!* +proxy.set('test', 1); // Error +*/!* +``` + +An attempt to set a value into a proxied `Map` fails, for the reason related to its [internal implementation](https://tc39.es/ecma262/#sec-map.prototype.set). + +Internally, a `Map` stores all data in its `[[MapData]]` internal slot. The proxy doesn't have such slot. The `set` method tries to access `this.[[MapData]]` internal property, but because `this=proxy`, can't find it in `proxy` and just fails. + +Fortunately, there's a way to fix it: + +```js run +let map = new Map(); + +let proxy = new Proxy(map, { + get(target, prop, receiver) { + let value = Reflect.get(...arguments); +*!* + return typeof value == 'function' ? value.bind(target) : value; +*/!* + } +}); + +proxy.set('test', 1); +alert(proxy.get('test')); // 1 (works!) +``` + +Now it works fine, because `get` trap binds function properties, such as `map.set`, to the target object (`map`) itself. + +Unlike the previous example, the value of `this` inside `proxy.set(...)` will be not `proxy`, but the original `map`. So when the internal implementation of `set` tries to access `this.[[MapData]]` internal slot, it succeeds. + +```smart header="`Array` has no internal slots" +A notable exception: built-in `Array` doesn't use internal slots. That's for historical reasons, as it appeared so long ago. + +So there's no such problem when proxying an array. +``` + +### Private fields + +The similar thing happens with private class fields. + +For example, `getName()` method accesses the private `#name` property and breaks after proxying: + +```js run +class User { + #name = "Guest"; + + getName() { + return this.#name; + } +} + +let user = new User(); + +user = new Proxy(user, {}); + +*!* +alert(user.getName()); // Error +*/!* +``` + +The reason is that private fields are implemented using internal slots. JavaScript does not use `[[Get]]/[[Set]]` when accessing them. + +In the call `user.getName()` the value of `this` is the proxied user, and it doesn't have the slot with private fields. + +Once again, the solution with binding the method makes it work: + +```js run +class User { + #name = "Guest"; + + getName() { + return this.#name; + } +} + +let user = new User(); + +user = new Proxy(user, { + get(target, prop, receiver) { + let value = Reflect.get(...arguments); + return typeof value == 'function' ? value.bind(target) : value; + } +}); + +alert(user.getName()); // Guest +``` + +That said, the solution has drawbacks, explained previously: it exposes the original object to the method, potentially allowing it to be passed further and breaking other proxied functionality. + +### Proxy != target + +Proxy and the original object are different objects. That's natural, right? + +So if we store the original object somewhere, and then proxy it, then things might break: + +```js run +let allUsers = new Set(); + +class User { + constructor(name) { + this.name = name; + allUsers.add(this); + } +} + +let user = new User("John"); + +alert(allUsers.has(user)); // true + +user = new Proxy(user, {}); + +*!* +alert(allUsers.has(user)); // false +*/!* +``` + +As we can see, after proxying we can't find `user` in the set `allUsers`, because the proxy is a different object. + +```warn header="Proxies can't intercept a strict equality test `===`" +Proxies can intercept many operators, such as `new` (with `construct`), `in` (with `has`), `delete` (with `deleteProperty`) and so on. + +But there's no way to intercept a strict equality test for objects. An object is strictly equal to itself only, and no other value. + +So all operations and built-in classes that compare objects for equality will differentiate between the object and the proxy. No transparent replacement here. +``` + + +## Revocable proxies + +A *revocable* proxy is a proxy that can be disabled. + +Let's say we have a resource, and would like to close access to it any moment. + +What we can do is to wrap it into a revocable proxy, without any traps. Such proxy will forward operations to object, and we also get a special method to disable it. + +The syntax is: + +```js +let {proxy, revoke} = Proxy.revocable(target, handler) +``` + +The call returns an object with the `proxy` and `revoke` function to disable it. + +Here's an example: + +```js run +let object = { + data: "Valuable data" +}; + +let {proxy, revoke} = Proxy.revocable(object, {}); + +// pass the proxy somewhere instead of object... +alert(proxy.data); // Valuable data + +// later in our code +revoke(); + +// the proxy isn't working any more (revoked) +alert(proxy.data); // Error +``` + +A call to `revoke()` removes all internal references to the target object from the proxy, so they are no more connected. The target object can be garbage-collected after that. + +We can also store `revoke` in a `WeakMap`, to be able to easily find it by the proxy: + + +```js run +*!* +let revokes = new WeakMap(); +*/!* + +let object = { + data: "Valuable data" +}; + +let {proxy, revoke} = Proxy.revocable(object, {}); + +revokes.set(proxy, revoke); + +// ..later in our code.. +revoke = revokes.get(proxy); +revoke(); + +alert(proxy.data); // Error (revoked) +``` + +The benefit of such approach is that we don't have to carry `revoke` around. We can get it from the map by `proxy` when needeed. + +Using `WeakMap` instead of `Map` here, because it should not block garbage collection. If a proxy object becomes "unreachable" (e.g. no variable references it any more), `WeakMap` allows it to be wiped from memory (we don't need its revoke in that case). + +## References + +- Specification: [Proxy](https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots). +- MDN: [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). + +## Summary + +`Proxy` is a wrapper around an object, that forwards operations to the object, optionally trapping some of them. + +It can wrap any kind of object, including classes and functions. + +The syntax is: + +```js +let proxy = new Proxy(target, { + /* traps */ +}); +``` + +...Then we should use `proxy` everywhere instead of `target`. A proxy doesn't have its own properties or methods. It traps an operation if the trap is provided or forwards it to `target` object. + +We can trap: +- Reading (`get`), writing (`set`), deleting (`deleteProperty`) a property (even a non-existing one). +- Calling functions with `new` (`construct` trap) and without `new` (`apply` trap) +- Many other operations (the full list is at the beginning of the article and in the [docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)). + +That allows us to create "virtual" properties and methods, implement default values, observable objects, function decorators and so much more. + +We can also wrap an object multiple times in different proxies, decorating it with various aspects of functionality. + +The [Reflect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect) API is designed to complement [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). For any `Proxy` trap, there's a `Reflect` call with same arguments. We should use those to forward calls to target objects. + +Proxies have some limitations: + +- Built-in objects have "internal slots", access to those can't be proxied. See the workaround above. +- The same holds true for private class fields, as they are internally implemented using slots. So proxied method calls must have the target object as `this` to access them. +- Object equality tests `===` can't be intercepted. +- Performance: benchmarks depend on an engine, but generally accessing a property using a simplest proxy takes a few times longer. In practice that only matters for some "bottleneck" objects though. diff --git a/10-misc/01-proxy/proxy-inherit.png b/10-misc/01-proxy/proxy-inherit.png new file mode 100644 index 0000000000000000000000000000000000000000..84110b6d60268aa317e638102c3a8991ce3135bb GIT binary patch literal 17381 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

=0!W44(rs3d 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 Gef&Q*Ur8GP literal 0 HcmV?d00001 diff --git a/10-misc/01-proxy/proxy.png b/10-misc/01-proxy/proxy.png new file mode 100644 index 0000000000000000000000000000000000000000..97aa073902bca8caf164f0db60aace1dbec46398 GIT binary patch literal 12488 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 b=(;b>-!m^Ka`JCbz>k!eyl91pLBRh3;>qaL literal 0 HcmV?d00001 diff --git a/2-ui/1-document/07-modifying-document/7-create-object-tree/build-tree-dom.view/index.html b/2-ui/1-document/07-modifying-document/7-create-object-tree/build-tree-dom.view/index.html index aec462fe..06d9c01b 100755 --- a/2-ui/1-document/07-modifying-document/7-create-object-tree/build-tree-dom.view/index.html +++ b/2-ui/1-document/07-modifying-document/7-create-object-tree/build-tree-dom.view/index.html @@ -17,7 +17,7 @@ "oak": {} }, "Flowering": { - "redbud": {}, + "apple tree": {}, "magnolia": {} } } diff --git a/2-ui/1-document/07-modifying-document/7-create-object-tree/innerhtml.view/index.html b/2-ui/1-document/07-modifying-document/7-create-object-tree/innerhtml.view/index.html index fd85e6c7..0f5f6b03 100644 --- a/2-ui/1-document/07-modifying-document/7-create-object-tree/innerhtml.view/index.html +++ b/2-ui/1-document/07-modifying-document/7-create-object-tree/innerhtml.view/index.html @@ -17,7 +17,7 @@ "oak": {} }, "Flowering": { - "redbud": {}, + "apple tree": {}, "magnolia": {} } } diff --git a/2-ui/1-document/07-modifying-document/7-create-object-tree/source.view/index.html b/2-ui/1-document/07-modifying-document/7-create-object-tree/source.view/index.html index d035aec6..8586f6b2 100755 --- a/2-ui/1-document/07-modifying-document/7-create-object-tree/source.view/index.html +++ b/2-ui/1-document/07-modifying-document/7-create-object-tree/source.view/index.html @@ -28,7 +28,7 @@

  • Flowering
      -
    • redbud
    • +
    • apple tree
    • magnolia
  • @@ -51,7 +51,7 @@ "oak": {} }, "Flowering": { - "redbud": {}, + "apple tree": {}, "magnolia": {} } } diff --git a/2-ui/1-document/07-modifying-document/7-create-object-tree/task.md b/2-ui/1-document/07-modifying-document/7-create-object-tree/task.md index 6b60c096..5ec1a01b 100644 --- a/2-ui/1-document/07-modifying-document/7-create-object-tree/task.md +++ b/2-ui/1-document/07-modifying-document/7-create-object-tree/task.md @@ -21,7 +21,7 @@ let data = { "oak": {} }, "Flowering": { - "redbud": {}, + "apple tree": {}, "magnolia": {} } } diff --git a/2-ui/1-document/07-modifying-document/article.md b/2-ui/1-document/07-modifying-document/article.md index 16aacb45..39f002cf 100644 --- a/2-ui/1-document/07-modifying-document/article.md +++ b/2-ui/1-document/07-modifying-document/article.md @@ -38,7 +38,7 @@ That was an HTML example. Now let's create the same `div` with JavaScript (assum To create DOM nodes, there are two methods: `document.createElement(tag)` -: Creates a new element with the given tag: +: Creates a new *element node* with the given tag: ```js let div = document.createElement('div'); @@ -67,7 +67,7 @@ After that, we have our DOM element ready. Right now it is just in a variable an To make the `div` show up, we need to insert it somewhere into `document`. For instance, in `document.body`. -There's a special method for that: `document.body.appendChild(div)`. +There's a special method `appendChild` for that: `document.body.appendChild(div)`. Here's the full code: @@ -146,9 +146,9 @@ Here's a brief list of methods to insert a node into a parent element (`parentEl All these methods return the inserted node. In other words, `parentElem.appendChild(node)` returns `node`. But usually the returned value is not used, we just run the method. -These methods are "old school": they exist from the ancient times and we can meet them in many old scripts. Unfortunately, there are some tasks that are hard to solve with them. +These methods are "old school": they exist from the ancient times and we can meet them in many old scripts. Unfortunately, they are not flexible enough. -For instance, how to insert *html* if we have it as a string? Or, given a node, how to insert another node *before* it? Of course, all that is doable, but not in an elegant way. +For instance, how to insert *html* if we have it as a string? Or, given a node, without reference to its parent, how to remove it? Of course, that's doable, but not in an elegant way. So there exist two other sets of insertion methods to handle all cases easily. @@ -162,6 +162,8 @@ This set of methods provides more flexible insertions: - `node.after(...nodes or strings)` –- insert nodes or strings after the `node`, - `node.replaceWith(...nodes or strings)` –- replaces `node` with the given nodes or strings. +All of them accept a list of DOM nodes and/or text strings. If a string is given it's inserted as a text node. + Here's an example of using these methods to add more items to a list and the text before/after it: ```html autorun @@ -236,14 +238,14 @@ But what if we want to insert HTML "as html", with all tags and stuff working, l There's another, pretty versatile method: `elem.insertAdjacentHTML(where, html)`. -The first parameter is a string, specifying where to insert. Must be one of the following: +The first parameter is a code word, specifying where to insert relative to `elem`. Must be one of the following: -- `"beforebegin"` -- insert `html` before `elem`, +- `"beforebegin"` -- insert `html` immediately before `elem`, - `"afterbegin"` -- insert `html` into `elem`, at the beginning, - `"beforeend"` -- insert `html` into `elem`, at the end, -- `"afterend"` -- insert `html` after `elem`. +- `"afterend"` -- insert `html` immediately after `elem`. -The second parameter is an HTML string, inserted "as is". +The second parameter is an HTML string, that is inserted "as HTML". For instance: @@ -338,9 +340,9 @@ An example of copying the message: ## DocumentFragment [#document-fragment] -`DocumentFragment` is a special DOM node that serves as a wrapper to pass around groups of nodes. +`DocumentFragment` is a special DOM node that serves as a wrapper to pass around lists of nodes. -We can append other nodes to it, but when we insert it somewhere, then it "disappears", leaving its content inserted instead. +We can append other nodes to it, but when we insert it somewhere, then its content is inserted instead. For example, `getListContent` below generates a fragment with `
  • ` items, that are later inserted into `