From b2cedf7b0a9b4c801b56d0768366fa0fdab964d4 Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Mon, 2 Sep 2019 23:43:51 +0300 Subject: [PATCH] closes #1308 --- .../09-call-apply-decorators/article.md | 15 ++++++++++----- 1-js/99-js-misc/01-proxy/article.md | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/article.md b/1-js/06-advanced-functions/09-call-apply-decorators/article.md index ceaf2b6a..8536cf31 100644 --- a/1-js/06-advanced-functions/09-call-apply-decorators/article.md +++ b/1-js/06-advanced-functions/09-call-apply-decorators/article.md @@ -61,7 +61,6 @@ To summarize, there are several benefits of using a separate `cachingDecorator` - The caching logic is separate, it did not increase the complexity of `slow` itself (if there was any). - We can combine multiple decorators if needed (other decorators will follow). - ## Using "func.call" for the context The caching decorator mentioned above is not suited to work with object methods. @@ -168,10 +167,8 @@ let user = { name: "John" }; say.call( user, "Hello" ); // John: Hello ``` - In our case, we can use `call` in the wrapper to pass the context to the original function: - ```js run let worker = { someMethod() { @@ -393,12 +390,20 @@ Taken from the specification almost "as-is": So, technically it takes `this` and joins `this[0]`, `this[1]` ...etc together. It's intentionally written in a way that allows any array-like `this` (not a coincidence, many methods follow this practice). That's why it also works with `this=arguments`. +## Decorators and function properties + +It is generally safe to replace a function or a method with a decorated one, except for one little thing. If the original function had properties on it, like `func.calledCount` or whatever, then the decorated one will not provide them. Because that is a wrapper. So one needs to be careful if one uses them. + +E.g. in the example above if `slow` function had any properties on it, then `cachingDecorator(slow)` is a wrapper without them. + +Some decorators may provide their own properties. E.g. a decorator may count how many times a function was invoked and how much time it took, and expose this information via wrapper properties. + +There exists a way to create decorators that keep access to function properties, but this requires using a special `Proxy` object to wrap a function. We'll discuss it later in the article . + ## Summary *Decorator* is a wrapper around a function that alters its behavior. The main job is still carried out by the function. -It is generally safe to replace a function or a method with a decorated one, except for one little thing. If the original function had properties on it, like `func.calledCount` or whatever, then the decorated one will not provide them. Because that is a wrapper. So one needs to be careful if one uses them. Some decorators provide their own properties. - Decorators can be seen as "features" or "aspects" that can be added to a function. We can add one or add many. And all this without changing its code! To implement `cachingDecorator`, we studied methods: diff --git a/1-js/99-js-misc/01-proxy/article.md b/1-js/99-js-misc/01-proxy/article.md index 943fcdc4..f6684af5 100644 --- a/1-js/99-js-misc/01-proxy/article.md +++ b/1-js/99-js-misc/01-proxy/article.md @@ -497,7 +497,7 @@ alert(50 in range); // false A nice syntactic sugar, isn't it? And very simple to implement. -## Wrapping functions: "apply" +## Wrapping functions: "apply" [#proxy-apply] We can wrap a proxy around a function as well.