From 861ef4a77025d849f56d14e4521927ebee43a528 Mon Sep 17 00:00:00 2001 From: vplentinax Date: Sun, 5 Jul 2020 16:11:04 -0400 Subject: [PATCH 1/7] syncJuly-5 --- 1-js/02-first-steps/09-comparison/article.md | 8 +- 1-js/05-data-types/02-number/article.md | 2 +- .../09-keys-values-entries/article.md | 2 +- .../03-closure/article.md | 2 +- .../5-sum-many-brackets/_js.view/solution.js | 15 ++++ .../5-sum-many-brackets/_js.view/source.js | 12 +++ .../5-sum-many-brackets/_js.view/test.js | 19 ++++ 1-js/09-classes/01-class/article.md | 31 ++----- .../02-class-inheritance/article.md | 89 ++++++++++++++++++- .../rabbit-extends-object.svg | 1 + .../3-class-extend-object/solution.md | 81 +++++++++++++++++ .../3-class-extend-object/task.md | 42 +++++++++ 1-js/11-async/05-promise-api/article.md | 8 +- 1-js/13-modules/01-modules-intro/article.md | 12 ++- .../01-browser-environment/article.md | 29 ++---- .../07-modifying-document/article.md | 29 ++++-- 2-ui/1-document/11-coordinates/article.md | 2 + .../6-pointer-events/article.md | 2 +- 6-data-storage/03-indexeddb/article.md | 6 +- .../03-regexp-unicode/article.md | 4 +- .../06-regexp-boundary/article.md | 2 +- 21 files changed, 321 insertions(+), 77 deletions(-) create mode 100644 1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/solution.js create mode 100644 1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/source.js create mode 100644 1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/test.js create mode 100644 1-js/09-classes/03-static-properties-methods/3-class-extend-object/rabbit-extends-object.svg create mode 100644 1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md create mode 100644 1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md diff --git a/1-js/02-first-steps/09-comparison/article.md b/1-js/02-first-steps/09-comparison/article.md index 76af2abab..8c73959db 100644 --- a/1-js/02-first-steps/09-comparison/article.md +++ b/1-js/02-first-steps/09-comparison/article.md @@ -2,11 +2,17 @@ Conocemos muchos operadores de comparación de las matemáticas: +En Javascript se escriben así: + - Mayor/menor que: a > b, a < b. - Mayor/menor o igual que: a >= b, a <= b. - Igual: `a == b` (ten en cuenta el doble signo `=`. Un solo símbolo `a = b` significaría una asignación). - Distinto. En matemáticas la notación es , pero en JavaScript se escribe como una asignación con un signo de exclamación delante: a != b. +En este artículo, aprenderemos más sobre los diferentes tipos de comparaciones, cómo las realiza JavaScript, incluidas las peculiaridades importantes. + +Al final, encontrará una buena receta para evitar problemas relacionados con "peculiaridades de JavaScript"("javascript quirks"). + ## Booleano es el resultado 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: - 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. - La comparación de igualdad `(3)` retorna `falso` porque `undefined` sólo equivale a `null` y a ningún otro valor. -### Evita los problemas +### Evitar los problemas ¿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: diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index 575b0cfcf..1c85b6381 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -148,7 +148,7 @@ Hay dos formas de hacerlo: 1. Multiplicar y dividir. - 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. + 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. ```js run let num = 1.23456; diff --git a/1-js/05-data-types/09-keys-values-entries/article.md b/1-js/05-data-types/09-keys-values-entries/article.md index 4af192515..b633dc274 100644 --- a/1-js/05-data-types/09-keys-values-entries/article.md +++ b/1-js/05-data-types/09-keys-values-entries/article.md @@ -74,7 +74,7 @@ Usually that's convenient. But if we want symbolic keys too, then there's a sepa Objects lack many methods that exist for arrays, e.g. `map`, `filter` and others. -If we'd like to apply them, then we can use `Object.entries` followed `Object.fromEntries`: +If we'd like to apply them, then we can use `Object.entries` followed by `Object.fromEntries`: 1. Use `Object.entries(obj)` to get an array of key/value pairs from `obj`. 2. Use array methods on that array, e.g. `map`. diff --git a/1-js/06-advanced-functions/03-closure/article.md b/1-js/06-advanced-functions/03-closure/article.md index 9d875899b..ff77ca979 100644 --- a/1-js/06-advanced-functions/03-closure/article.md +++ b/1-js/06-advanced-functions/03-closure/article.md @@ -184,7 +184,7 @@ Los rectángulos en el lado derecho demuestran cómo cambia el entorno léxico g 1. Cuando se inicia el script, el entorno léxico se rellena previamente con todas las variables declaradas.      - 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. -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. +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. 3. `phrase` se le asigna un valor. 4. `phrase` cambia el valor. diff --git a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/solution.js b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/solution.js new file mode 100644 index 000000000..c7d7d734e --- /dev/null +++ b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/solution.js @@ -0,0 +1,15 @@ +function sum(a) { + + let currentSum = a; + + function f(b) { + currentSum += b; + return f; + } + + f.toString = function() { + return currentSum; + }; + + return f; +} diff --git a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/source.js b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/source.js new file mode 100644 index 000000000..f10dca5dc --- /dev/null +++ b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/source.js @@ -0,0 +1,12 @@ +function sum(a){ + // Your code goes here. + +} + +/* +sum(1)(2) == 3; // 1 + 2 +sum(1)(2)(3) == 6; // 1 + 2 + 3 +sum(5)(-1)(2) == 6 +sum(6)(-1)(-2)(-3) == 0 +sum(0)(1)(2)(3)(4)(5) == 15 +*/ diff --git a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/test.js b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/test.js new file mode 100644 index 000000000..ed567d330 --- /dev/null +++ b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/_js.view/test.js @@ -0,0 +1,19 @@ +describe("sum", function(){ + + it("sum(1)(2) == 3", function(){ + assert.equal(3, sum(1)(2)); + }); + + it("sum(5)(-1)(2) == 6", function(){ + assert.equal(6, sum(5)(-1)(2)); + }); + + it("sum(6)(-1)(-2)(-3) == 0", function(){ + assert.equal(0, sum(6)(-1)(-2)(-3)); + }); + + it("sum(0)(1)(2)(3)(4)(5) == 15", function(){ + assert.equal(15, sum(0)(1)(2)(3)(4)(5)); + }); +}); + diff --git a/1-js/09-classes/01-class/article.md b/1-js/09-classes/01-class/article.md index 672d40215..835143e94 100644 --- a/1-js/09-classes/01-class/article.md +++ b/1-js/09-classes/01-class/article.md @@ -331,7 +331,7 @@ alert(user.name); // John alert(User.prototype.name); // undefined ``` -Technically, they are processed after the constructor has done it's job, and we can use for them complex expressions and function calls: +We can also assign values using more complex expressions and function calls: ```js run class User { @@ -375,30 +375,9 @@ The problem is called "losing `this`". There are two approaches to fixing it, as discussed in the chapter : 1. Pass a wrapper-function, such as `setTimeout(() => button.click(), 1000)`. -2. Bind the method to object, e.g. in the constructor: +2. Bind the method to object, e.g. in the constructor. -```js run -class Button { - constructor(value) { - this.value = value; -*!* - this.click = this.click.bind(this); -*/!* - } - - click() { - alert(this.value); - } -} - -let button = new Button("hello"); - -*!* -setTimeout(button.click, 1000); // hello -*/!* -``` - -Class fields provide a more elegant syntax for the latter solution: +Class fields provide another, quite elegant syntax: ```js run class Button { @@ -417,9 +396,9 @@ let button = new Button("hello"); setTimeout(button.click, 1000); // hello ``` -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`. +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. -That's especially useful in browser environment, when we need to setup a method as an event listener. +That's especially useful in browser environment, for event listeners. ## Summary diff --git a/1-js/09-classes/02-class-inheritance/article.md b/1-js/09-classes/02-class-inheritance/article.md index 3d3c145eb..526a5218a 100644 --- a/1-js/09-classes/02-class-inheritance/article.md +++ b/1-js/09-classes/02-class-inheritance/article.md @@ -230,7 +230,8 @@ let rabbit = new Rabbit("White Rabbit", 10); // Error: this is not defined. Whoops! We've got an error. Now we can't create rabbits. What went wrong? -The short answer is: constructors in inheriting classes must call `super(...)`, and (!) do it before using `this`. +The short answer is: +- **Constructors in inheriting classes must call `super(...)`, and (!) do it before using `this`.** ...But why? What's going on here? Indeed, the requirement seems strange. @@ -243,7 +244,7 @@ That label affects its behavior with `new`. - When a regular function is executed with `new`, it creates an empty object and assigns it to `this`. - But when a derived constructor runs, it doesn't do this. It expects the parent constructor to do this job. -So a derived constructor must call `super` in order to execute its parent (non-derived) constructor, otherwise the object for `this` won't be created. And we'll get an error. +So a derived constructor must call `super` in order to execute its parent (base) constructor, otherwise the object for `this` won't be created. And we'll get an error. For the `Rabbit` constructor to work, it needs to call `super()` before using `this`, like here: @@ -277,7 +278,91 @@ alert(rabbit.name); // White Rabbit alert(rabbit.earLength); // 10 */!* ``` +### Overriding class fields: a tricky note +```warn header="Advanced note" +This note assumes you have a certain experience with classes, maybe in other programming languages. +It provides better insight into the language and also explains the behavior that might be a source of bugs (but not very often). +If you find it difficult to understand, just go on, continue reading, then return to it some time later. +``` + +We can override not only methods, but also class fields. + +Although, there's a tricky behavior when we access an overridden field in parent constructor, quite different from most other programming languages. + +Consider this example: + +```js run +class Animal { + name = 'animal' + constructor() { + alert(this.name); // (*) + } +} +class Rabbit extends Animal { + name = 'rabbit'; +} +new Animal(); // animal +*!* +new Rabbit(); // animal +*/!* +``` + +Here, class `Rabbit` extends `Animal` and overrides `name` field with its own value. + +There's no own constructor in `Rabbit`, so `Animal` constructor is called. + +What's interesting is that in both cases: `new Animal()` and `new Rabbit()`, the `alert` in the line `(*)` shows `animal`. + +**In other words, parent constructor always uses its own field value, not the overridden one.** + +What's odd about it? + +If it's not clear yet, please compare with methods. + +Here's the same code, but instead of `this.name` field we call `this.showName()` method: + +```js run +class Animal { + showName() { // instead of this.name = 'animal' + alert('animal'); + } + constructor() { + this.showName(); // instead of alert(this.name); + } +} +class Rabbit extends Animal { + showName() { + alert('rabbit'); + } +} +new Animal(); // animal +*!* +new Rabbit(); // rabbit +*/!* +``` + +Please note: now the output is different. + +And that's what we naturally expect. When the parent constructor is called in the derived class, it uses the overridden method. + +...But for class fields it's not so. As said, the parent constructor always uses the parent field. + +Why is there the difference? + +Well, the reason is in the field initialization order. The class field is initialized: +- Before constructor for the base class (that doesn't extend anything), +- Imediately after `super()` for the derived class. + +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)`. + +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. + +This subtle difference between fields and methods is specific to JavaScript + +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. + +If it becomes a problem, one can fix it by using methods or getters/setters instead of fields. ## Super: internals, [[HomeObject]] diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/rabbit-extends-object.svg b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/rabbit-extends-object.svg new file mode 100644 index 000000000..34d783b4d --- /dev/null +++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/rabbit-extends-object.svg @@ -0,0 +1 @@ +call: function bind: function ...Function.prototypeconstructorObjectRabbit[[Prototype]][[Prototype]]constructorcall: function bind: function ...Function.prototypeRabbit[[Prototype]]constructorclass Rabbitclass Rabbit extends Object \ No newline at end of file diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md new file mode 100644 index 000000000..ca9e80601 --- /dev/null +++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md @@ -0,0 +1,81 @@ +First, let's see why the latter code doesn't work. + +The reason becomes obvious if we try to run it. An inheriting class constructor must call `super()`. Otherwise `"this"` won't be "defined". + +So here's the fix: + +```js run +class Rabbit extends Object { + constructor(name) { +*!* + super(); // need to call the parent constructor when inheriting +*/!* + this.name = name; + } +} + +let rabbit = new Rabbit("Rab"); + +alert( rabbit.hasOwnProperty('name') ); // true +``` + +But that's not all yet. + +Even after the fix, there's still important difference in `"class Rabbit extends Object"` versus `class Rabbit`. + +As we know, the "extends" syntax sets up two prototypes: + +1. Between `"prototype"` of the constructor functions (for methods). +2. Between the constructor functions themselves (for static methods). + +In our case, for `class Rabbit extends Object` it means: + +```js run +class Rabbit extends Object {} + +alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true +alert( Rabbit.__proto__ === Object ); // (2) true +``` + +So `Rabbit` now provides access to static methods of `Object` via `Rabbit`, like this: + +```js run +class Rabbit extends Object {} + +*!* +// normally we call Object.getOwnPropertyNames +alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b +*/!* +``` + +But if we don't have `extends Object`, then `Rabbit.__proto__` is not set to `Object`. + +Here's the demo: + +```js run +class Rabbit {} + +alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true +alert( Rabbit.__proto__ === Object ); // (2) false (!) +alert( Rabbit.__proto__ === Function.prototype ); // as any function by default + +*!* +// error, no such function in Rabbit +alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error +*/!* +``` + +So `Rabbit` doesn't provide access to static methods of `Object` in that case. + +By the way, `Function.prototype` has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`. + +Here's the picture: + +![](rabbit-extends-object.svg) + +So, to put it short, there are two differences: + +| class Rabbit | class Rabbit extends Object | +|--------------|------------------------------| +| -- | needs to call `super()` in constructor | +| `Rabbit.__proto__ === Function.prototype` | `Rabbit.__proto__ === Object` | diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md new file mode 100644 index 000000000..1d0f98a74 --- /dev/null +++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md @@ -0,0 +1,42 @@ +importance: 3 + +--- + +# Class extends Object? + +As we know, all objects normally inherit from `Object.prototype` and get access to "generic" object methods like `hasOwnProperty` etc. + +For instance: + +```js run +class Rabbit { + constructor(name) { + this.name = name; + } +} + +let rabbit = new Rabbit("Rab"); + +*!* +// hasOwnProperty method is from Object.prototype +alert( rabbit.hasOwnProperty('name') ); // true +*/!* +``` + +But if we spell it out explicitly like `"class Rabbit extends Object"`, then the result would be different from a simple `"class Rabbit"`? + +What's the difference? + +Here's an example of such code (it doesn't work -- why? fix it?): + +```js +class Rabbit extends Object { + constructor(name) { + this.name = name; + } +} + +let rabbit = new Rabbit("Rab"); + +alert( rabbit.hasOwnProperty('name') ); // Error +``` diff --git a/1-js/11-async/05-promise-api/article.md b/1-js/11-async/05-promise-api/article.md index e6be25008..191f6ed21 100644 --- a/1-js/11-async/05-promise-api/article.md +++ b/1-js/11-async/05-promise-api/article.md @@ -179,10 +179,10 @@ If the browser doesn't support `Promise.allSettled`, it's easy to polyfill: if(!Promise.allSettled) { Promise.allSettled = function(promises) { return Promise.all(promises.map(p => Promise.resolve(p).then(value => ({ - state: 'fulfilled', + status: 'fulfilled', value }), reason => ({ - state: 'rejected', + status: 'rejected', reason })))); }; @@ -191,7 +191,7 @@ if(!Promise.allSettled) { 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. -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`. +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`. Now we can use `Promise.allSettled` to get the results of *all* given promises, even if some of them reject. @@ -277,7 +277,7 @@ There are 5 static methods of `Promise` class: 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. 2. `Promise.allSettled(promises)` (recently added method) -- waits for all promises to settle and returns their results as an array of objects with: - - `state`: `"fulfilled"` or `"rejected"` + - `status`: `"fulfilled"` or `"rejected"` - `value` (if fulfilled) or `reason` (if rejected). 3. `Promise.race(promises)` -- waits for the first promise to settle, and its result/error becomes the outcome. 4. `Promise.resolve(value)` -- makes a resolved promise with the given value. diff --git a/1-js/13-modules/01-modules-intro/article.md b/1-js/13-modules/01-modules-intro/article.md index 5534cbb94..4e7cb518d 100644 --- a/1-js/13-modules/01-modules-intro/article.md +++ b/1-js/13-modules/01-modules-intro/article.md @@ -1,13 +1,13 @@ # Módulos, introducción -A medida que nuestra aplicación crece, queremos dividirla en múltiples archivos, llamados "módulos". Un módulo generalmente contiene una clase o una biblioteca de funciones. +A medida que nuestra aplicación crece, queremos dividirla en múltiples archivos, llamados "módulos". Un módulo contener una clase o una biblioteca de funciones para un propósito específico. Durante mucho tiempo, JavaScript existió sin una sintaxis de módulo a nivel de lenguaje. Eso no fue un problema, porque inicialmente los scripts eran pequeños y simples, por lo que no era necesario. Pero con el tiempo los scripts se volvieron cada vez más complejos, por lo que la comunidad inventó una variedad de formas de organizar el código en módulos, bibliotecas especiales para cargar módulos a pedido. -Por ejemplo: +Para nombrar algunos (por razones históricas): - [AMD](https://es.wikipedia.org/wiki/Asynchronous_module_definition) -- uno de los sistemas de módulos más antiguos, implementado inicialmente por la biblioteca [require.js](http://requirejs.org/). - [CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1) -- el sistema de módulos creado para el servidor Node.js. @@ -15,11 +15,11 @@ Por ejemplo: Ahora, todo esto se convierte lentamente en una parte de la historia, pero aún podemos encontrarlos en viejos scripts. -El sistema de módulos a nivel de idioma apareció en el estándar en 2015, evolucionó gradualmente desde entonces y ahora es compatible con todos los principales navegadores y en Node.js. Así que lo estudiaremos de ahora en adelante. +El sistema de módulos a nivel de idioma apareció en el estándar en 2015, evolucionó gradualmente desde entonces y ahora es compatible con todos los principales navegadores y en Node.js. Así que estudiaremos los módulos modernos de Javascript de ahora en adelante. ## Qué es un módulo? -Un módulo es solo un archivo. Un script es un módulo. +Un módulo es solo un archivo. Un script es un módulo. Tan sencillo como eso. Los módulos pueden cargarse entre sí y usar directivas especiales `export` e `import` para intercambiar funcionalidad, llamar a funciones de un módulo de otro: @@ -57,6 +57,10 @@ Asi: El navegador busca y evalúa automáticamente el módulo importado (y sus importaciones si es necesario), y luego ejecuta el script. +```warn header="Modules work only via HTTP(s), not in local files" +Si intenta abrir una página web localmente, a través del protocolo `file://`, encontrará que las directivas `import / export` no funcionan. Use un servidor web local, como [static-server](https://www.npmjs.com/package/static-server#getting-started) o use la capacidad de "servidor en vivo" de su editor, como VS Código [Live Server Extension](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) para probar los módulos. +``` + ## Características del módulo central ¿Qué hay de diferente en los módulos en comparación con los scripts "normales"? diff --git a/2-ui/1-document/01-browser-environment/article.md b/2-ui/1-document/01-browser-environment/article.md index 02e5fc322..a9ca47764 100644 --- a/2-ui/1-document/01-browser-environment/article.md +++ b/2-ui/1-document/01-browser-environment/article.md @@ -2,7 +2,7 @@ El lenguaje JavaScript fue creado inicialmente para los navegadores web. Desde entonces, ha evolucionado y se ha convertido en un lenguaje con muchos usos y plataformas. -Una plataforma puede ser un navegador, un servidor web, una lavadora u otro *host (anfitrión)*. Cada uno de ellos proporciona una funcionalidad específica. La especificación de JavaScript lo llama *entorno host*. +Una plataforma puede ser un navegador, un servidor web u otro *host*, incluso una máquina de café "inteligente", si puede ejecutar JavaScript. Cada uno de ellos proporciona una funcionalidad específica de la plataforma. La especificación de JavaScript llama esto como *entorno de host*(host enviroment). Un entorno host proporciona objetos específicos de la plataforma y funciones adicionales al núcleo del lenguaje. Los navegadores web proporcionan un medio para controlar las páginas web. Node.JS proporciona características del lado del servidor, y así sucesivamente. @@ -47,31 +47,18 @@ document.body.style.background = "red"; setTimeout(() => document.body.style.background = "", 1000); ``` -Aquí usamos `document.body.style`, pero hay muchos, muchos más. Las propiedades y métodos se describen en la especificación. Sucede que hay dos grupos de trabajo que lo desarrollan: +Aquí usamos `document.body.style`, pero hay muchos, muchos más. Las propiedades y métodos se describen en la especificación: [DOM Living Standard](https://dom.spec.whatwg.org). -1. [W3C](https://es.wikipedia.org/wiki/World_Wide_Web_Consortium) -- la documentación se encuentra en . -2. [WhatWG](https://es.wikipedia.org/wiki/Web_Hypertext_Application_Technology_Working_Group), publicado en . +```smart header="DOM is not only for browsers" +La especificación DOM explica la estructura de un documento y proporciona objetos para manipularlo. Hay instrumentos que no son del navegador que también usan DOM. -Como es de esperar, los dos grupos no siempre están de acuerdo, así que es como si tuviéramos dos conjuntos de estándares. Pero son muy similares y eventualmente las cosas se fusionan. La documentación que puede encontrar en los recursos dados es muy similar, con aproximadamente un 99% de coincidencia. Hay diferencias muy pequeñas que probablemente no notarás. - -Personalmente, encuentro más agradable de usar. - -En el pasado lejano, no existía ninguna norma en absoluto: cada navegador lo implementaba como quería. Diferentes navegadores tenían diferentes métodos y propiedades para la misma cosa, y los desarrolladores tenían que escribir un código diferente para cada uno de ellos. Tiempos oscuros, desordenados. - -Incluso ahora, podemos encontrarnos con código antiguo que usa propiedades específicas del navegador y soluciona las incompatibilidades. Pero, en este tutorial usaremos cosas modernas: no hay necesidad de aprender cosas antiguas hasta que realmente lo necesites (es muy probable que no lo hagas). - -Luego apareció el estándar DOM, en un intento de llevar a todos a un acuerdo. La primera versión fue "DOM Level 1", luego fue extendida por DOM Level 2, luego DOM Level 3, y ahora llegó a DOM Level 4. La gente del grupo WhatWG se cansó de los números de versión y lo están llamando simplemente "DOM", sin un numero. Así que haremos lo mismo. - -```smart header="DOM no es solo para navegadores" -La especificación DOM explica la estructura de un documento y proporciona objetos para manipularlo. Hay instrumentos que no son del navegador que también lo utilizan. - -Por ejemplo, las herramientas del lado del servidor que descargan páginas HTML y las procesan utilizan el DOM. Sin embargo, pueden soportar solo una parte de la especificación. +Por ejemplo, los scripts del lado del servidor que descargan páginas HTML y las procesan, también pueden usar DOM. Sin embargo, pueden admitir solo una parte de la especificación. ``` -```smart header="CSSOM para los estilos" -Las reglas CSS y las hojas de estilo no están estructuradas como HTML. Hay una especificación [CSSOM](https://www.w3.org/TR/cssom-1/) separada, que explica cómo se representan como objetos, y cómo leerlos y escribirlos. +```smart header="CSSOM for styling" +También hay una especificación separada, [CSS Object Model (CSSOM)] (https://www.w3.org/TR/cssom-1/) para las reglas y hojas de estilo CSS, que explica cómo se representan como objetos y cómo leerlos y escribirlos. -CSSOM se usa junto con DOM cuando modificamos las reglas de estilo para el documento. En la práctica, sin embargo, rara vez se requiere CSSOM, porque generalmente las reglas de CSS son estáticas. Rara vez necesitamos agregar/eliminar reglas CSS desde JavaScript, por lo que no lo cubriremos ahora. +CSSOM se usa junto con DOM cuando modificamos las reglas de estilo para el documento. Sin embargo, en la práctica, rara vez se requiere CSSOM, porque rara vez necesitamos modificar las reglas CSS de JavaScript (generalmente solo agregamos / eliminamos clases CSS, no modificamos sus reglas CSS), pero eso también es posible. ``` ## BOM (parte de la especificación HTML) diff --git a/2-ui/1-document/07-modifying-document/article.md b/2-ui/1-document/07-modifying-document/article.md index c4796a1d4..6dfb2fe22 100644 --- a/2-ui/1-document/07-modifying-document/article.md +++ b/2-ui/1-document/07-modifying-document/article.md @@ -28,7 +28,7 @@ Here's how it will look: */!* ``` -That was an HTML example. Now let's create the same `div` with JavaScript (assuming that the styles are in the HTML or an external CSS file). +That was the HTML example. Now let's create the same `div` with JavaScript (assuming that the styles are in the HTML/CSS already). ## Creating an element @@ -48,21 +48,26 @@ To create DOM nodes, there are two methods: let textNode = document.createTextNode('Here I am'); ``` +Most of the time we need to create element nodes, such as the `div` for the message. + ### Creating the message -In our case the message is a `div` with `alert` class and the HTML in it: +Creating the message div takes 3 steps: ```js +// 1. Create
element let div = document.createElement('div'); +// 2. Set its class to "alert" div.className = "alert"; +// Fill it with the content div.innerHTML = "Hi there! You've read an important message."; ``` -We created the element, but as of now it's only in a variable. We can't see the element on the page, as it's not yet a part of the document. +We've created the element. But as of now it's only in a variable named `div`, not in the page yet. So we can't see it. ## Insertion methods -To make the `div` show up, we need to insert it somewhere into `document`. For instance, in `document.body`. +To make the `div` show up, we need to insert it somewhere into `document`. For instance, into `` element, referenced by `document.body`. There's a special method `append` for that: `document.body.append(div)`. @@ -90,7 +95,9 @@ Here's the full code: ``` -This set of methods provides more ways to insert: +Here we called `append` on `document.body`, but we can call `append` method on any other element, to put another element into it. For instance, we can append something to `
` by calling `div.append(anotherElement)`. + +Here are more insertion methods, they specify different places where to insert: - `node.append(...nodes or strings)` -- append nodes or strings at the end of `node`, - `node.prepend(...nodes or strings)` -- insert nodes or strings at the beginning of `node`, @@ -98,6 +105,10 @@ This set of methods provides more ways to insert: - `node.after(...nodes or strings)` –- insert nodes or strings after `node`, - `node.replaceWith(...nodes or strings)` –- replaces `node` with the given nodes or strings. +Arguments of these methods are an arbitrary list of DOM nodes to insert, or text strings (that become text nodes automatically). + +Let's see them in action. + Here's an example of using these methods to add items to a list and the text before/after it: ```html autorun @@ -121,7 +132,7 @@ Here's an example of using these methods to add items to a list and the text bef ``` -Here's a visual picture what methods do: +Here's a visual picture of what the methods do: ![](before-prepend-append-after.svg) @@ -139,7 +150,7 @@ before after ``` -These methods can insert multiple lists of nodes and text pieces in a single call. +As said, these methods can insert multiple nodes and text pieces in a single call. For instance, here a string and an element are inserted: @@ -150,7 +161,7 @@ For instance, here a string and an element are inserted: ``` -All text is inserted *as text*. +Please note: the text is inserted "as text", not "as HTML", with proper escaping of characters such as `<`, `>`. So the final HTML is: @@ -166,7 +177,7 @@ In other words, strings are inserted in a safe way, like `elem.textContent` does So, these methods can only be used to insert DOM nodes or text pieces. -But what if we want to insert HTML "as html", with all tags and stuff working, like `elem.innerHTML`? +But what if we'd like to insert an HTML string "as html", with all tags and stuff working, in the same manner as `elem.innerHTML` does it? ## insertAdjacentHTML/Text/Element diff --git a/2-ui/1-document/11-coordinates/article.md b/2-ui/1-document/11-coordinates/article.md index b4b577cd0..fb55edf57 100644 --- a/2-ui/1-document/11-coordinates/article.md +++ b/2-ui/1-document/11-coordinates/article.md @@ -216,6 +216,8 @@ function getCoords(elem) { return { top: box.top + window.pageYOffset, + right: box.right + window.pageXOffset, + bottom: box.bottom + window.pageYOffset, left: box.left + window.pageXOffset }; } diff --git a/2-ui/3-event-details/6-pointer-events/article.md b/2-ui/3-event-details/6-pointer-events/article.md index 734b76bd8..658465d39 100644 --- a/2-ui/3-event-details/6-pointer-events/article.md +++ b/2-ui/3-event-details/6-pointer-events/article.md @@ -177,7 +177,7 @@ But we continue tracking track `pointermove` events and move the thumb until `po [Previously](info:mouse-drag-and-drop), to handle `pointermove` events that happen outside of the slider, we listened for `pointermove` events on the whole `document`. -Pointer capturing provides an alternative solution: we can call `thumb.setPointerCapture(event.pointerId)` in `pointerdown` handler, and then all future pointer events until `pointerup` will be retarteted to `thumb`. +Pointer capturing provides an alternative solution: we can call `thumb.setPointerCapture(event.pointerId)` in `pointerdown` handler, and then all future pointer events until `pointerup` will be retargeted to `thumb`. That is: events handlers on `thumb` will be called, and `event.target` will always be `thumb`, even if the user moves their pointer around the whole document. So we can listen at `thumb` for `pointermove`, no matter where it happens. diff --git a/6-data-storage/03-indexeddb/article.md b/6-data-storage/03-indexeddb/article.md index 7b93fd12b..3f0cf0e5a 100644 --- a/6-data-storage/03-indexeddb/article.md +++ b/6-data-storage/03-indexeddb/article.md @@ -5,7 +5,7 @@ libs: # IndexedDB -IndexedDB is a database, that is built into browser, much more powerful than `localStorage`. +IndexedDB is a database that is built into browser, much more powerful than `localStorage`. - Stores almost any kind of values by keys, multiple key types. - Supports transactions for reliability. @@ -75,10 +75,10 @@ We can open it with version `2` and perform the upgrade like this: ```js let openRequest = indexedDB.open("store", *!*2*/!*); -openRequest.onupgradeneeded = function() { +openRequest.onupgradeneeded = function(event) { // the existing database version is less than 2 (or it doesn't exist) let db = openRequest.result; - switch(db.version) { // existing db version + switch(event.oldVersion) { // existing db version case 0: // version 0 means that the client had no database // perform initialization diff --git a/9-regular-expressions/03-regexp-unicode/article.md b/9-regular-expressions/03-regexp-unicode/article.md index fb8fed470..defbe15ab 100644 --- a/9-regular-expressions/03-regexp-unicode/article.md +++ b/9-regular-expressions/03-regexp-unicode/article.md @@ -93,7 +93,7 @@ Here's the main character categories and their subcategories: - control `Cc`, - format `Cf`, - not assigned `Cn`, - -- private use `Co`, + - private use `Co`, - surrogate `Cs`. @@ -127,7 +127,7 @@ alert("number: xAF".match(regexp)); // xAF Let's look for Chinese hieroglyphs. -There's a unicode property `Script` (a writing system), that may have a value: `Cyrillic`, `Greek`, `Arabic`, `Han` (Chinese) and so on, [here's the full list]("https://en.wikipedia.org/wiki/Script_(Unicode)"). +There's a unicode property `Script` (a writing system), that may have a value: `Cyrillic`, `Greek`, `Arabic`, `Han` (Chinese) and so on, [here's the full list](https://en.wikipedia.org/wiki/Script_(Unicode)). To look for characters in a given writing system we should use `pattern:Script=`, e.g. for Cyrillic letters: `pattern:\p{sc=Cyrillic}`, for Chinese hieroglyphs: `pattern:\p{sc=Han}`, and so on: diff --git a/9-regular-expressions/06-regexp-boundary/article.md b/9-regular-expressions/06-regexp-boundary/article.md index aad65877f..7c9f442fe 100644 --- a/9-regular-expressions/06-regexp-boundary/article.md +++ b/9-regular-expressions/06-regexp-boundary/article.md @@ -25,7 +25,7 @@ So, it matches the pattern `pattern:\bHello\b`, because: 1. At the beginning of the string matches the first test `pattern:\b`. 2. Then matches the word `pattern:Hello`. -3. Then the test `pattern:\b` matches again, as we're between `subject:o` and a space. +3. Then the test `pattern:\b` matches again, as we're between `subject:o` and a comma. The pattern `pattern:\bHello\b` would also match. But not `pattern:\bHell\b` (because there's no word boundary after `l`) and not `Java!\b` (because the exclamation sign is not a wordly character `pattern:\w`, so there's no word boundary after it). From 240f32ffe98df2f14bc4b4d1b093638f013bbfbc Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Mon, 6 Jul 2020 14:39:53 -0400 Subject: [PATCH 2/7] Update 1-js/13-modules/01-modules-intro/article.md Co-authored-by: Ezequiel Castellanos <51804994+ezzep66@users.noreply.github.com> --- 1-js/13-modules/01-modules-intro/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/13-modules/01-modules-intro/article.md b/1-js/13-modules/01-modules-intro/article.md index 4e7cb518d..79fde983c 100644 --- a/1-js/13-modules/01-modules-intro/article.md +++ b/1-js/13-modules/01-modules-intro/article.md @@ -1,7 +1,7 @@ # Módulos, introducción -A medida que nuestra aplicación crece, queremos dividirla en múltiples archivos, llamados "módulos". Un módulo contener una clase o una biblioteca de funciones para un propósito específico. +A medida que nuestra aplicación crece, queremos dividirla en múltiples archivos, llamados "módulos". Un módulo puede contener una clase o una biblioteca de funciones para un propósito específico. Durante mucho tiempo, JavaScript existió sin una sintaxis de módulo a nivel de lenguaje. Eso no fue un problema, porque inicialmente los scripts eran pequeños y simples, por lo que no era necesario. From abb90a91a23f10f5604cd67e5d184e943884d295 Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Mon, 6 Jul 2020 14:40:09 -0400 Subject: [PATCH 3/7] Update 1-js/13-modules/01-modules-intro/article.md Co-authored-by: Ezequiel Castellanos <51804994+ezzep66@users.noreply.github.com> --- 1-js/13-modules/01-modules-intro/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/13-modules/01-modules-intro/article.md b/1-js/13-modules/01-modules-intro/article.md index 79fde983c..b2fd74a3c 100644 --- a/1-js/13-modules/01-modules-intro/article.md +++ b/1-js/13-modules/01-modules-intro/article.md @@ -57,7 +57,7 @@ Asi: El navegador busca y evalúa automáticamente el módulo importado (y sus importaciones si es necesario), y luego ejecuta el script. -```warn header="Modules work only via HTTP(s), not in local files" +```warn header="Los módulos funcionan solo a través de HTTP(s), no en archivos locales" Si intenta abrir una página web localmente, a través del protocolo `file://`, encontrará que las directivas `import / export` no funcionan. Use un servidor web local, como [static-server](https://www.npmjs.com/package/static-server#getting-started) o use la capacidad de "servidor en vivo" de su editor, como VS Código [Live Server Extension](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) para probar los módulos. ``` From f8ab700372c5c07b2c2cd8077a06c461efbfad42 Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Mon, 6 Jul 2020 14:40:32 -0400 Subject: [PATCH 4/7] Update 2-ui/1-document/01-browser-environment/article.md Co-authored-by: Ezequiel Castellanos <51804994+ezzep66@users.noreply.github.com> --- 2-ui/1-document/01-browser-environment/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/1-document/01-browser-environment/article.md b/2-ui/1-document/01-browser-environment/article.md index a9ca47764..47968a689 100644 --- a/2-ui/1-document/01-browser-environment/article.md +++ b/2-ui/1-document/01-browser-environment/article.md @@ -2,7 +2,7 @@ El lenguaje JavaScript fue creado inicialmente para los navegadores web. Desde entonces, ha evolucionado y se ha convertido en un lenguaje con muchos usos y plataformas. -Una plataforma puede ser un navegador, un servidor web u otro *host*, incluso una máquina de café "inteligente", si puede ejecutar JavaScript. Cada uno de ellos proporciona una funcionalidad específica de la plataforma. La especificación de JavaScript llama esto como *entorno de host*(host enviroment). +Una plataforma puede ser un navegador, un servidor web u otro *host*, incluso una máquina de café "inteligente", si puede ejecutar JavaScript. Cada uno de ellos proporciona una funcionalidad específica de la plataforma. La especificación de JavaScript llama esto como *entorno de host* (host enviroment). Un entorno host proporciona objetos específicos de la plataforma y funciones adicionales al núcleo del lenguaje. Los navegadores web proporcionan un medio para controlar las páginas web. Node.JS proporciona características del lado del servidor, y así sucesivamente. From ce707cca73e1b545cf087852a5c0f0269251fd3c Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Mon, 6 Jul 2020 14:40:40 -0400 Subject: [PATCH 5/7] Update 2-ui/1-document/01-browser-environment/article.md Co-authored-by: Ezequiel Castellanos <51804994+ezzep66@users.noreply.github.com> --- 2-ui/1-document/01-browser-environment/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/1-document/01-browser-environment/article.md b/2-ui/1-document/01-browser-environment/article.md index 47968a689..2e38cb88c 100644 --- a/2-ui/1-document/01-browser-environment/article.md +++ b/2-ui/1-document/01-browser-environment/article.md @@ -55,7 +55,7 @@ La especificación DOM explica la estructura de un documento y proporciona objet Por ejemplo, los scripts del lado del servidor que descargan páginas HTML y las procesan, también pueden usar DOM. Sin embargo, pueden admitir solo una parte de la especificación. ``` -```smart header="CSSOM for styling" +```smart header="CSSOM para los estilos" También hay una especificación separada, [CSS Object Model (CSSOM)] (https://www.w3.org/TR/cssom-1/) para las reglas y hojas de estilo CSS, que explica cómo se representan como objetos y cómo leerlos y escribirlos. CSSOM se usa junto con DOM cuando modificamos las reglas de estilo para el documento. Sin embargo, en la práctica, rara vez se requiere CSSOM, porque rara vez necesitamos modificar las reglas CSS de JavaScript (generalmente solo agregamos / eliminamos clases CSS, no modificamos sus reglas CSS), pero eso también es posible. From 1f7e30e9b0a21045ab85f914dbc099fa49ab1e06 Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Mon, 6 Jul 2020 14:40:50 -0400 Subject: [PATCH 6/7] Update 2-ui/1-document/01-browser-environment/article.md Co-authored-by: Ezequiel Castellanos <51804994+ezzep66@users.noreply.github.com> --- 2-ui/1-document/01-browser-environment/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/1-document/01-browser-environment/article.md b/2-ui/1-document/01-browser-environment/article.md index 2e38cb88c..a21773706 100644 --- a/2-ui/1-document/01-browser-environment/article.md +++ b/2-ui/1-document/01-browser-environment/article.md @@ -49,7 +49,7 @@ setTimeout(() => document.body.style.background = "", 1000); Aquí usamos `document.body.style`, pero hay muchos, muchos más. Las propiedades y métodos se describen en la especificación: [DOM Living Standard](https://dom.spec.whatwg.org). -```smart header="DOM is not only for browsers" +```smart header="DOM no es solo para navegadores" La especificación DOM explica la estructura de un documento y proporciona objetos para manipularlo. Hay instrumentos que no son del navegador que también usan DOM. Por ejemplo, los scripts del lado del servidor que descargan páginas HTML y las procesan, también pueden usar DOM. Sin embargo, pueden admitir solo una parte de la especificación. From 1929ea37173d5a2c9d7e4387a1932d91ca7406b0 Mon Sep 17 00:00:00 2001 From: Valentina VP <34555644+vplentinax@users.noreply.github.com> Date: Tue, 7 Jul 2020 11:37:38 -0400 Subject: [PATCH 7/7] Update 1-js/13-modules/01-modules-intro/article.md Co-authored-by: joaquinelio --- 1-js/13-modules/01-modules-intro/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/13-modules/01-modules-intro/article.md b/1-js/13-modules/01-modules-intro/article.md index b2fd74a3c..f30b1aacd 100644 --- a/1-js/13-modules/01-modules-intro/article.md +++ b/1-js/13-modules/01-modules-intro/article.md @@ -58,7 +58,7 @@ Asi: El navegador busca y evalúa automáticamente el módulo importado (y sus importaciones si es necesario), y luego ejecuta el script. ```warn header="Los módulos funcionan solo a través de HTTP(s), no en archivos locales" -Si intenta abrir una página web localmente, a través del protocolo `file://`, encontrará que las directivas `import / export` no funcionan. Use un servidor web local, como [static-server](https://www.npmjs.com/package/static-server#getting-started) o use la capacidad de "servidor en vivo" de su editor, como VS Código [Live Server Extension](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) para probar los módulos. +Si intenta abrir una página web localmente a través del protocolo `file://`, encontrará que las directivas `import / export` no funcionan. Use un servidor web local, como [static-server](https://www.npmjs.com/package/static-server#getting-started) o use la capacidad de "servidor en vivo" de su editor, como VS Code [Live Server Extension](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) para probar los módulos. ``` ## Características del módulo central