Skip to content

Proxy and Reflect #422

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions 1-js/99-js-misc/01-proxy/01-error-nonexisting/solution.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function wrap(target) {
if (prop in target) {
return Reflect.get(target, prop, receiver);
} else {
throw new ReferenceError(`Property doesn't exist: "${prop}"`)
throw new ReferenceError(`A propriedade não existe: "${prop}"`)
}
}
});
Expand All @@ -19,5 +19,5 @@ function wrap(target) {
user = wrap(user);

alert(user.name); // John
alert(user.age); // ReferenceError: Property doesn't exist: "age"
alert(user.age); // ReferenceError: A propriedade não existe: "age"
```
16 changes: 8 additions & 8 deletions 1-js/99-js-misc/01-proxy/01-error-nonexisting/task.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Error on reading non-existent property
# Erro ao ler propriedade inexistente

Usually, an attempt to read a non-existent property returns `undefined`.
Normalmente, uma tentativa de ler uma propriedade inexistente retorna `undefined`.

Create a proxy that throws an error for an attempt to read of a non-existent property instead.
Crie um proxy que lança um erro numa tentativa de ler uma propriedade inexistente.

That can help to detect programming mistakes early.
Isso pode ajudar a detectar erros de programação antecipadamente.

Write a function `wrap(target)` that takes an object `target` and return a proxy that adds this functionality aspect.
Escreva uma função `wrap(target)` que recebe um objeto `target` e retorna um proxy que adiciona esse aspecto funcional

That's how it should work:
É assim que deve funcionar:

```js
let user = {
Expand All @@ -18,7 +18,7 @@ let user = {
function wrap(target) {
return new Proxy(target, {
*!*
/* your code */
/* seu código */
*/!*
});
}
Expand All @@ -27,6 +27,6 @@ user = wrap(user);

alert(user.name); // John
*!*
alert(user.age); // ReferenceError: Property doesn't exist: "age"
alert(user.age); // ReferenceError: A propriedade não existe: "age"
*/!*
```
4 changes: 2 additions & 2 deletions 1-js/99-js-misc/01-proxy/02-array-negative/solution.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ 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
// mesmo se acessarmos como arr[1]
// prop é uma string, então é necessário convertê-la para um número.
prop = +prop + target.length;
}
return Reflect.get(target, prop, receiver);
Expand Down
22 changes: 11 additions & 11 deletions 1-js/99-js-misc/01-proxy/02-array-negative/task.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@

# Accessing array[-1]
# Acessando array[-1]

In some programming languages, we can access array elements using negative indexes, counted from the end.
Em algumas linguagens de programação, podemos acessar elementos de um array usando índices negativos, contados a partir do final.

Like this:
Assim:

```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
array[-1]; // 3, o último elemento
array[-2]; // 2, uma posição a partir da última
array[-3]; // 1, duas posições a partir da última
```

In other words, `array[-N]` is the same as `array[array.length - N]`.
Em outras palavras, `array[-N]` é o mesmo que `array[array.length - N]`.

Create a proxy to implement that behavior.
Crie um proxy para implementar esse comportamento.

That's how it should work:
É assim que deve funcionar:

```js
let array = [1, 2, 3];

array = new Proxy(array, {
/* your code */
/* seu código */
});

alert( array[-1] ); // 3
alert( array[-2] ); // 2

// Other array functionality should be kept "as is"
// Outras funcionalidades do array devem ser mantidas "como estão".
```
18 changes: 9 additions & 9 deletions 1-js/99-js-misc/01-proxy/03-observable/solution.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
The solution consists of two parts:
A solução consiste em duas partes:

1. Whenever `.observe(handler)` is called, we need to remember the handler somewhere, to be able to call it later. We can store handlers right in the object, using our symbol as the property key.
2. We need a proxy with `set` trap to call handlers in case of any change.
1. Sempre que `.observe(handler)` for chamado, precisamos lembrar handler em algum lugar, para ser possível chamá-lo mais tarde. Podemos armazenar os handlers diretamente no objeto, usando nosso symbol como chave da propriedade.
2. Precisamos de um proxy com uma armadilha (trap) `set` para chamar os handlers no caso de alguma mudança.

```js run
let handlers = Symbol('handlers');

function makeObservable(target) {
// 1. Initialize handlers store
// 1. Inicializa o armazenamento de manipuladores
target[handlers] = [];

// Store the handler function in array for future calls
// Armazena a função handler no array para futuras chamadas
target.observe = function(handler) {
this[handlers].push(handler);
};

// 2. Create a proxy to handle changes
// 2. Cria um proxy para lidar com as mudanças
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
let success = Reflect.set(...arguments); // Encaminha a operação para o objeto
if (success) { // Se não houve erro ao definir a propriedade
// chama rodos os handlers
target[handlers].forEach(handler => handler(property, value));
}
return success;
Expand Down
14 changes: 7 additions & 7 deletions 1-js/99-js-misc/01-proxy/03-observable/task.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@

# Observable

Create a function `makeObservable(target)` that "makes the object observable" by returning a proxy.
Crie uma função makeObservable(target) que "torna o objeto observável" ao retornar um proxy.

Here's how it should work:
Aqui está como deveria funcionar:

```js run
function makeObservable(target) {
/* your code */
/* seu código */
}

let user = {};
Expand All @@ -17,11 +17,11 @@ user.observe((key, value) => {
alert(`SET ${key}=${value}`);
});

user.name = "John"; // alerts: SET name=John
user.name = "John"; // alerta: SET name=John
```

In other words, an object returned by `makeObservable` is just like the original one, but also has the method `observe(handler)` that sets `handler` function to be called on any property change.
Em outras palavras, um objeto retornado por `makeObservable` é exatamente como o original, mas também possui o método `observe(handler)` que define a função `handler` para ser chamada em qualquer alteração de propriedade.

Whenever a property changes, `handler(key, value)` is called with the name and value of the property.
Sempre que uma propriedade muda, `handler(key, value)` é chamado com o nome e o valor da propriedade.

P.S. In this task, please only take care about writing to a property. Other operations can be implemented in a similar way.
P.S. Nesta tarefa, preocupe-se apenas com a escrita em uma propriedade. Outras operações podem ser implementadas de maneira semelhante.
Loading