Skip to content

Commit fea0c5a

Browse files
committed
Edited ch06.asciidoc with Atlas code editor
1 parent 5e81897 commit fea0c5a

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

ch06.asciidoc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ proxy['something-else']
4646
// <- undefined
4747
----
4848

49-
As a complement to proxies, ES6 introduces a `Reflect` ((("Reflect")))built-in object. The traps in ES6 proxies are mapped one-to-one to the `Reflect` API: For every trap, there’s a matching reflection method in `Reflect`. These methods can be particularly useful when we want the default behavior of proxy traps, but we don't want to concern ourselves with the implementation of that behavior.
49+
As a complement to proxies, ES6 introduces a `Reflect` ((("Reflect")))built-in object. The traps in ES6 proxies are mapped one-to-one to the `Reflect` API: for every trap, there’s a matching reflection method in `Reflect`. These methods can be particularly useful when we want the default behavior of proxy traps, but we don't want to concern ourselves with the implementation of that behavior.
5050

5151
In the following code snippet we use `Reflect.get` to provide the default behavior for `get` operations, while not worrying about accessing the `key` property in `target` by hand. While in this case the operation may seem trivial, the default behavior for other traps may be harder to remember and implement correctly. We can forward every parameter in the trap to the reflection API and return its result.
5252

@@ -185,7 +185,7 @@ const proxy = concealWithPrefix(target)
185185
// expose proxy to consumers
186186
----
187187

188-
You might be tempted to argue that you could achieve the same behavior in ES5 simply by using variables privately scoped to the `concealWithPrefix` function, without the need for the `Proxy` itself. The difference is that proxies allow you to "privatize" property access dynamically. Without relying on `Proxy`, you couldn't mark every property that starts with an underscore as private. You could use `Object.freeze`​footnoteref:[object-freeze,The `Object.freeze` method prevents adding new properties, removing existing ones, and modifying property value references. Note that it doesn't make the values themselves immutable: their properties can still change provided `Object.freeze` isn't called on those objects as well.] on the object, but then you wouldn't be able to modify the property references yourself, either. Or you could define get and set accessors for every property, but then again you wouldn't be able to block access on every single property, only the ones you explicitly configured getters and ((("traps", startref="trap6")))((("set traps", startref="st6")))in ((("traps", "set traps", startref="trap6st")))((("proxies", "set traps and", startref="prox6sta")))setters for.
188+
You might be tempted to argue that you could achieve the same behavior in ES5 simply by using variables privately scoped to the `concealWithPrefix` function, without the need for the `Proxy` itself. The difference is that proxies allow you to "privatize" property access dynamically. Without relying on `Proxy`, you couldn't mark every property that starts with an underscore as private. You could use `Object.freeze`​footnoteref:[object-freeze,The `Object.freeze` method prevents adding new properties, removing existing ones, and modifying property value references. Note that it doesn't make the values themselves immutable: their properties can still change, provided `Object.freeze` isn't called on those objects as well.] on the object, but then you wouldn't be able to modify the property references yourself, either. Or you could define get and set accessors for every property, but then again you wouldn't be able to block access on every single property, only the ones you explicitly configured getters and ((("traps", startref="trap6")))((("set traps", startref="st6")))in ((("traps", "set traps", startref="trap6st")))((("proxies", "set traps and", startref="prox6sta")))setters for.
189189

190190
==== Schema Validation with Proxies
191191

@@ -285,7 +285,7 @@ function revokeStorage(proxy) {
285285
}
286286
----
287287

288-
Given that `revoke` is available on the same scope where your `handler` traps are defined, you could set up unforgiving access rules such that if a consumer attempts to access a private property more than once you revoke their `proxy` ((("proxies", "revokable", startref="prox6r")))((("revokable proxies", startref="rp6")))access entirely.
288+
Given that `revoke` is available on the same scope where your `handler` traps are defined, you could set up unforgiving access rules such that if a consumer attempts to access a private property more than once, you revoke their `proxy` ((("proxies", "revokable", startref="prox6r")))((("revokable proxies", startref="rp6")))access entirely.
289289

290290
=== Proxy Trap Handlers
291291

@@ -697,7 +697,7 @@ console.log(proxy.hasOwnProperty('_secret'))
697697

698698
When you're trying to hide things, it's best to have them try and behave as if they fell in some other category than the category they're actually in, thus concealing their behavior and passing it off for something else. Throwing, however, sends the wrong message when we want to conceal something: why does a property throw instead of return `undefined`? It must exist but be inaccessible. This is not unlike situations in HTTP API design where we might prefer to return "404 Not Found" responses for sensitive resources, such as an administration backend, when the user is unauthorized to access them, instead of the technically correct "401 Unauthorized" status code.
699699

700-
When debugging concerns outweight security concerns, you should at least consider the `throw` statement. In any case, it's important to understand your use case in order to figure out the optimal and least surprising behavior for a given ((("getOwnPropertyDescriptor trap", startref="gopdt6")))((("proxies", "getOwnPropertyDescriptor trap", startref="prox6gopdt")))((("traps", "getOwnPropertyDescriptor trap", startref="t6gopdt")))component.
700+
When debugging concerns outweigh security concerns, you should at least consider the `throw` statement. In any case, it's important to understand your use case in order to figure out the optimal and least surprising behavior for a given ((("getOwnPropertyDescriptor trap", startref="gopdt6")))((("proxies", "getOwnPropertyDescriptor trap", startref="prox6gopdt")))((("traps", "getOwnPropertyDescriptor trap", startref="t6gopdt")))component.
701701

702702
==== apply Trap
703703

@@ -1093,4 +1093,4 @@ As we've learned over the last few pages, there are myriad use cases for proxies
10931093

10941094
Proxies are an extremely powerful feature in ES6, with many potential applications, and they're well equipped for code instrumentation and introspection. However, they also have a significant performance impact in JavaScript engine execution as they're virtually impossible to optimize for. This makes proxies impractical for applications where speed is of the essence.
10951095

1096-
At the same time it's easy to confuse consumers by providing complicated proxies that attempt to do too much. It may be a good idea to avoid them for most use cases, or at least develop consistent and uncomplicated access rules. Make sure you're not producing many side-effects in property access, which can lead to confusion even if properly ((("proxies", startref="prox6")))documented.
1096+
At the same time it's easy to confuse consumers by providing complicated proxies that attempt to do too much. It may be a good idea to avoid them for most use cases, or at least develop consistent and uncomplicated access rules. Make sure you're not producing many side effects in property access, which can lead to confusion even if properly ((("proxies", startref="prox6")))documented.

0 commit comments

Comments
 (0)