Skip to content

Commit c2a0dc3

Browse files
Merge pull request #293 from vplentinax/syncJuly-5
Sincronización 5 Julio
2 parents b02ef3a + 0dd12c7 commit c2a0dc3

File tree

18 files changed

+193
-74
lines changed

18 files changed

+193
-74
lines changed

1-js/02-first-steps/09-comparison/article.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@
22

33
Conocemos muchos operadores de comparación de las matemáticas:
44

5+
En Javascript se escriben así:
6+
57
- Mayor/menor que: <code>a &gt; b</code>, <code>a &lt; b</code>.
68
- Mayor/menor o igual que: <code>a &gt;= b</code>, <code>a &lt;= b</code>.
79
- Igual: `a == b` (ten en cuenta el doble signo `=`. Un solo símbolo `a = b` significaría una asignación).
810
- Distinto. En matemáticas la notación es <code>&ne;</code>, pero en JavaScript se escribe como una asignación con un signo de exclamación delante: <code>a != b</code>.
911

12+
En este artículo, aprenderemos más sobre los diferentes tipos de comparaciones, cómo las realiza JavaScript, incluidas las peculiaridades importantes.
13+
14+
Al final, encontrará una buena receta para evitar problemas relacionados con "peculiaridades de JavaScript"("javascript quirks").
15+
1016
## Booleano es el resultado
1117

1218
Como todos los demás operadores, una comparación retorna un valor. En este caso, el valor es un booleano.
@@ -195,7 +201,7 @@ Obtenemos estos resultados porque:
195201
- Las comparaciones `(1)` y `(2)` retornan `falso` porque `no definido` se convierte en `NaN` y `NaN` es un valor numérico especial que retorna `falso` para todas las comparaciones.
196202
- La comparación de igualdad `(3)` retorna `falso` porque `undefined` sólo equivale a `null` y a ningún otro valor.
197203

198-
### Evita los problemas
204+
### Evitar los problemas
199205

200206
¿Por qué repasamos estos ejemplos? ¿Deberíamos recordar estas peculiaridades todo el tiempo? Bueno, en realidad no. En realidad, estas cosas difíciles se volverán familiares con el tiempo, pero hay una manera sólida de evadir los problemas con ellas:
201207

1-js/05-data-types/02-number/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ Hay dos formas de hacerlo:
148148

149149
1. Multiplicar y dividir.
150150

151-
Para redondear el número a dos dígitos tras el decimal, podemos multiplicarlo por `100`, llamar la función de redondeo y volverlo a dividir.
151+
Para redondear el número a dos dígitos tras el decimal, podemos multiplicarlo por `100` (o una potencia mayor de 10), llamar la función de redondeo y volverlo a dividir.
152152
```js run
153153
let num = 1.23456;
154154

1-js/05-data-types/09-keys-values-entries/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Usually that's convenient. But if we want symbolic keys too, then there's a sepa
7474

7575
Objects lack many methods that exist for arrays, e.g. `map`, `filter` and others.
7676

77-
If we'd like to apply them, then we can use `Object.entries` followed `Object.fromEntries`:
77+
If we'd like to apply them, then we can use `Object.entries` followed by `Object.fromEntries`:
7878

7979
1. Use `Object.entries(obj)` to get an array of key/value pairs from `obj`.
8080
2. Use array methods on that array, e.g. `map`.

1-js/06-advanced-functions/03-closure/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ Los rectángulos en el lado derecho demuestran cómo cambia el entorno léxico g
184184

185185
1. Cuando se inicia el script, el entorno léxico se rellena previamente con todas las variables declaradas.
186186
     - Inicialmente, están en el estado "No inicializado". Ese es un estado interno especial, significa que el motor conoce la variable, pero no se puede hacer referencia a ella hasta que se haya declarado con `let`. Es casi lo mismo que si la variable no existiera.
187-
2. Luego aparece la definición `let phrase`.Todavía no hay una asignación, por lo que su valor es `undefined`. Podemos usar la variable desde este momento.
187+
2. Luego aparece la definición `let phrase`.Todavía no hay una asignación, por lo que su valor es `undefined`. Podemos usar la variable desde este punto en adelante.
188188
3. `phrase` se le asigna un valor.
189189
4. `phrase` cambia el valor.
190190

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
function sum(a) {
2+
3+
let currentSum = a;
4+
5+
function f(b) {
6+
currentSum += b;
7+
return f;
8+
}
9+
10+
f.toString = function() {
11+
return currentSum;
12+
};
13+
14+
return f;
15+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function sum(a){
2+
// Your code goes here.
3+
4+
}
5+
6+
/*
7+
sum(1)(2) == 3; // 1 + 2
8+
sum(1)(2)(3) == 6; // 1 + 2 + 3
9+
sum(5)(-1)(2) == 6
10+
sum(6)(-1)(-2)(-3) == 0
11+
sum(0)(1)(2)(3)(4)(5) == 15
12+
*/
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
describe("sum", function(){
2+
3+
it("sum(1)(2) == 3", function(){
4+
assert.equal(3, sum(1)(2));
5+
});
6+
7+
it("sum(5)(-1)(2) == 6", function(){
8+
assert.equal(6, sum(5)(-1)(2));
9+
});
10+
11+
it("sum(6)(-1)(-2)(-3) == 0", function(){
12+
assert.equal(0, sum(6)(-1)(-2)(-3));
13+
});
14+
15+
it("sum(0)(1)(2)(3)(4)(5) == 15", function(){
16+
assert.equal(15, sum(0)(1)(2)(3)(4)(5));
17+
});
18+
});
19+

1-js/09-classes/01-class/article.md

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ alert(user.name); // John
331331
alert(User.prototype.name); // undefined
332332
```
333333

334-
Technically, they are processed after the constructor has done it's job, and we can use for them complex expressions and function calls:
334+
We can also assign values using more complex expressions and function calls:
335335

336336
```js run
337337
class User {
@@ -375,30 +375,9 @@ The problem is called "losing `this`".
375375
There are two approaches to fixing it, as discussed in the chapter <info:bind>:
376376

377377
1. Pass a wrapper-function, such as `setTimeout(() => button.click(), 1000)`.
378-
2. Bind the method to object, e.g. in the constructor:
378+
2. Bind the method to object, e.g. in the constructor.
379379

380-
```js run
381-
class Button {
382-
constructor(value) {
383-
this.value = value;
384-
*!*
385-
this.click = this.click.bind(this);
386-
*/!*
387-
}
388-
389-
click() {
390-
alert(this.value);
391-
}
392-
}
393-
394-
let button = new Button("hello");
395-
396-
*!*
397-
setTimeout(button.click, 1000); // hello
398-
*/!*
399-
```
400-
401-
Class fields provide a more elegant syntax for the latter solution:
380+
Class fields provide another, quite elegant syntax:
402381

403382
```js run
404383
class Button {
@@ -417,9 +396,9 @@ let button = new Button("hello");
417396
setTimeout(button.click, 1000); // hello
418397
```
419398

420-
The class field `click = () => {...}` creates an independent function on each `Button` object, with `this` bound to the object. Then we can pass `button.click` around anywhere, and it will be called with the right `this`.
399+
The class field `click = () => {...}` is created on a per-object basis, there's a separate function for each `Button` object, with `this` inside it referencing that object. We can pass `button.click` around anywhere, and the value of `this` will always be correct.
421400

422-
That's especially useful in browser environment, when we need to setup a method as an event listener.
401+
That's especially useful in browser environment, for event listeners.
423402

424403
## Summary
425404

1-js/09-classes/02-class-inheritance/article.md

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ let rabbit = new Rabbit("Conejo Blanco", 10); // Error: esto no está definido.
230230

231231
Vaya! Tenemos un error. Ahora no podemos crear conejos. ¿Qué salió mal?
232232

233-
La respuesta corta es: los constructores en las clases heredadas deben llamar a `super(...)`, y (!) Hacerlo antes de usar `this`.
233+
La respuesta corta es:
234+
- **Los constructores en las clases heredadas deben llamar a `super(...)`, y (!) hacerlo antes de usar `this`**.
234235

235236
...¿Pero por qué? ¿Que está pasando aqui? De hecho, el requisito parece extraño.
236237

@@ -243,7 +244,7 @@ Esa etiqueta afecta su comportamiento con `new`.
243244
- Cuando una función regular se ejecuta con `new`, crea un objeto vacío y lo asigna a `this`.
244245
- Pero cuando se ejecuta un constructor derivado, no hace esto. Espera que el constructor padre haga este trabajo.
245246

246-
Por lo tanto, un constructor derivado debe llamar a `super` para ejecutar su constructor padre (no derivado), de lo contrario no se creará el objeto para `this`. Y obtendremos un error.
247+
**Por lo tanto, un constructor derivado debe llamar a `super` para ejecutar su constructor padre (no derivado), de lo contrario no se creará el objeto para `this`. Y obtendremos un error.**
247248

248249
Para que el constructor `Rabbit` funcione, necesita llamar a `super()` antes de usar `this`, como aquí:
249250

@@ -277,7 +278,91 @@ alert(rabbit.name); // Conejo Blanco
277278
alert(rabbit.earLength); // 10
278279
*/!*
279280
```
281+
### Overriding class fields: a tricky note
280282

283+
```warn header="Advanced note"
284+
This note assumes you have a certain experience with classes, maybe in other programming languages.
285+
It provides better insight into the language and also explains the behavior that might be a source of bugs (but not very often).
286+
If you find it difficult to understand, just go on, continue reading, then return to it some time later.
287+
```
288+
289+
We can override not only methods, but also class fields.
290+
291+
Although, there's a tricky behavior when we access an overridden field in parent constructor, quite different from most other programming languages.
292+
293+
Consider this example:
294+
295+
```js run
296+
class Animal {
297+
name = 'animal'
298+
constructor() {
299+
alert(this.name); // (*)
300+
}
301+
}
302+
class Rabbit extends Animal {
303+
name = 'rabbit';
304+
}
305+
new Animal(); // animal
306+
*!*
307+
new Rabbit(); // animal
308+
*/!*
309+
```
310+
311+
Here, class `Rabbit` extends `Animal` and overrides `name` field with its own value.
312+
313+
There's no own constructor in `Rabbit`, so `Animal` constructor is called.
314+
315+
What's interesting is that in both cases: `new Animal()` and `new Rabbit()`, the `alert` in the line `(*)` shows `animal`.
316+
317+
**In other words, parent constructor always uses its own field value, not the overridden one.**
318+
319+
What's odd about it?
320+
321+
If it's not clear yet, please compare with methods.
322+
323+
Here's the same code, but instead of `this.name` field we call `this.showName()` method:
324+
325+
```js run
326+
class Animal {
327+
showName() { // instead of this.name = 'animal'
328+
alert('animal');
329+
}
330+
constructor() {
331+
this.showName(); // instead of alert(this.name);
332+
}
333+
}
334+
class Rabbit extends Animal {
335+
showName() {
336+
alert('rabbit');
337+
}
338+
}
339+
new Animal(); // animal
340+
*!*
341+
new Rabbit(); // rabbit
342+
*/!*
343+
```
344+
345+
Please note: now the output is different.
346+
347+
And that's what we naturally expect. When the parent constructor is called in the derived class, it uses the overridden method.
348+
349+
...But for class fields it's not so. As said, the parent constructor always uses the parent field.
350+
351+
Why is there the difference?
352+
353+
Well, the reason is in the field initialization order. The class field is initialized:
354+
- Before constructor for the base class (that doesn't extend anything),
355+
- Imediately after `super()` for the derived class.
356+
357+
In our case, `Rabbit` is the derived class. There's no `constructor()` in it. As said previously, that's the same as if there was an empty constructor with only `super(...args)`.
358+
359+
So, `new Rabbit()` calls `super()`, thus executing the parent constructor, and (per the rule for derived classes) only after that its class fields are initialized. At the time of the parent constructor execution, there are no `Rabbit` class fields yet, that's why `Animal` fields are used.
360+
361+
This subtle difference between fields and methods is specific to JavaScript
362+
363+
Luckily, this behavior only reveals itself if an overridden field is used in the parent constructor. Then it may be difficult to understand what's going on, so we're explaining it here.
364+
365+
If it becomes a problem, one can fix it by using methods or getters/setters instead of fields.
281366

282367
## [[HomeObject]]: el `super` interno
283368

1-js/11-async/05-promise-api/article.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,10 @@ If the browser doesn't support `Promise.allSettled`, it's easy to polyfill:
179179
if(!Promise.allSettled) {
180180
Promise.allSettled = function(promises) {
181181
return Promise.all(promises.map(p => Promise.resolve(p).then(value => ({
182-
state: 'fulfilled',
182+
status: 'fulfilled',
183183
value
184184
}), reason => ({
185-
state: 'rejected',
185+
status: 'rejected',
186186
reason
187187
}))));
188188
};
@@ -191,7 +191,7 @@ if(!Promise.allSettled) {
191191
192192
In this code, `promises.map` takes input values, turns them into promises (just in case a non-promise was passed) with `p => Promise.resolve(p)`, and then adds `.then` handler to every one.
193193
194-
That handler turns a successful result `value` into `{state:'fulfilled', value}`, and an error `reason` into `{state:'rejected', reason}`. That's exactly the format of `Promise.allSettled`.
194+
That handler turns a successful result `value` into `{status:'fulfilled', value}`, and an error `reason` into `{status:'rejected', reason}`. That's exactly the format of `Promise.allSettled`.
195195
196196
Now we can use `Promise.allSettled` to get the results of *all* given promises, even if some of them reject.
197197
@@ -277,7 +277,7 @@ There are 5 static methods of `Promise` class:
277277
278278
1. `Promise.all(promises)` -- waits for all promises to resolve and returns an array of their results. If any of the given promises rejects, it becomes the error of `Promise.all`, and all other results are ignored.
279279
2. `Promise.allSettled(promises)` (recently added method) -- waits for all promises to settle and returns their results as an array of objects with:
280-
- `state`: `"fulfilled"` or `"rejected"`
280+
- `status`: `"fulfilled"` or `"rejected"`
281281
- `value` (if fulfilled) or `reason` (if rejected).
282282
3. `Promise.race(promises)` -- waits for the first promise to settle, and its result/error becomes the outcome.
283283
4. `Promise.resolve(value)` -- makes a resolved promise with the given value.

0 commit comments

Comments
 (0)