Hola a todos! A finales de septiembre, una nueva transmisión del curso
"Fullstack JavaScript Developer" comenzará en
OTUS . En previsión del comienzo de las clases, queremos compartir con ustedes un artículo de autor preparado especialmente para los estudiantes del curso.
Autor del artículo: Pavel Yakupov
Vista previa Quiero señalar de inmediato que en este artículo se examinan temas que son familiares para los "ninjas", y el artículo tiene como objetivo más hacer que los principiantes comprendan mejor algunos de los matices del lenguaje y no perderse en las tareas que a menudo dan durante una entrevista, después de todo, tales Las tareas no tienen nada que ver con el desarrollo real, y aquellos que las realizan, con mayor frecuencia de esta manera, tratan de comprender qué tan bien conoce JavaScript.

Tipos de memoria de referencia
¿Cómo se almacenan exactamente los datos en JavaScript? Muchos cursos de programación comienzan a explicar con el clásico: una variable es una especie de "caja" en la que almacenamos algunos datos. Cuáles, para los idiomas con escritura dinámica, parece que no importa: el propio intérprete "traga" cualquier tipo de datos y cambia el tipo dinámicamente si es necesario, y no debe pensar en los tipos de variables y cómo se procesan. Lo que, por supuesto, está mal, y por lo tanto, comenzaremos la discusión de hoy con características que a menudo se escapan: cómo se almacenan las variables en JavaScript, en forma de primitivas (copias) o en forma de enlaces.
Enumeraremos inmediatamente los tipos de variables que se pueden almacenar en forma de primitivas: estas son
boolean
,
null
,
undefined
,
Number
,
String
,
Symbol
,
BigInt
. Cuando encontramos variables declaradas por separado con este tipo de datos, debemos recordar que durante la inicialización inicial crean una celda de memoria, y que se pueden asignar, copiar, transferir y devolver por valor.
El resto de JavaScript se basa en áreas de memoria referenciadas. ¿Por qué son necesarios? Los creadores del lenguaje intentaron crear un lenguaje en el que la memoria se usara de la forma más económica posible (y esto no era absolutamente nuevo en ese momento). Para ilustrar, imagine que necesita recordar los nombres de tres nuevos colegas de trabajo: nombres completamente nuevos y para mejorar la comparación, sus nuevos colegas de India o China con nombres inusuales para usted. Ahora imagine que sus colegas son llamados como usted y sus dos mejores amigos en la escuela. ¿En qué situación será más fácil de recordar? Aquí, la memoria de una persona y una computadora funciona de manera similar. Aquí hay algunos ejemplos específicos:
let x = 15;
Por lo tanto, si encuentra una tarea similar en una entrevista, intente comprender de inmediato qué tipo de datos tiene frente a usted, de dónde provienen y cómo obtuvo el valor, como un tipo primitivo o como referencia.

Trabajo contextual
Para comprender exactamente cómo funciona el contexto en JS, debe estudiar algunos puntos:
- Nivel de visibilidad global / local.
- La diferencia de contexto al inicializar variables en el ámbito global / local.
- Funciones de flecha.
Érase una vez, en ES5, todo era bastante simple: solo había una declaración de variable usando var, que cuando se declaraba en el flujo del programa se consideraba global (lo que significaba que la variable se asignaba como una propiedad a un objeto global, como
window
o
global
). Luego,
let
y
const
llegaron a la escena, que se comportan de manera algo diferente: no están asignados al objeto global y se almacenan en la memoria de manera diferente, centrándose en el alcance del bloque. Ahora var ya se considera obsoleto, porque su uso puede conducir a la obstrucción del alcance global y, además,
let
vea mucho más predecible.
1. Entonces, para comprenderlo, vale la pena entender claramente cuáles son los alcances en JavaScript (alcance). Si una variable se declara en el ámbito global utilizando la directiva
let
, no se asigna al objeto de
window
, sino que se guarda globalmente.
Pasemos a las tareas que los principiantes suelen hacer con preguntas contextuales en la entrevista.
//: ? let x = 15; function foo(){ let x = 13; return x; } console.log(x)// 15 foo(); console.log(x)// x = foo(); console.log(x)// return ,
2. Al mismo tiempo, no todos los principiantes son conscientes de cómo el intérprete de JavaScript lee el código: de hecho, lo lee dos veces, la primera vez que lee el código de funciones declarado como Declaración de funciones (y está listo para ejecutarlas en la segunda lectura y ejecución real) ) Otro pequeño truco está relacionado con
var
y
let
: la primera vez que se lee una variable con la directiva
var
, se establece como
undefined
. Pero con
let
su llamada prematura no es posible en absoluto:
console.log(x); console.log(y) var x = 42; let y = 38;
3. Las funciones de flecha que aparecieron en ES6 rápidamente ganaron popularidad: los programadores las adoptaron muy rápidamente en
Node.js (debido a una rápida actualización del motor) y
React (debido a las características de la biblioteca y al uso inevitable de Babel). Con respecto al contexto, las funciones de flecha se adhieren a la siguiente regla: no se unen a
this
. Ilustramos esto:
var x = 4; var y = 4; function mult(){ return this.x * this.y; } let foo = mult.bind(this); console.log(foo()); let muliply = ()=>x*y; console.log(muliply()); /* x y let, function declaration */

Tipos de datos y a qué se aplica
Digamos de inmediato: una matriz es esencialmente un objeto, y en JavaScript esta no es la primera variación de un objeto: Map, WeakSet, Set y colecciones lo confirman.
Por lo tanto, una matriz es un objeto, y su diferencia con un objeto regular en JS se debe principalmente a una mayor velocidad debido a la optimización de la indexación y, en segundo lugar, a la herencia de Array.prototype, que proporciona un conjunto más amplio de métodos, razón por la cual Gran Hermano »
Object.prototype
.
console.log(typeof({})) console.log(typeof([])) console.log(typeof(new Set)) console.log(typeof(new Map)) //
El siguiente en la cola de rarezas en los tipos de datos es
null
. Si le pregunta a JavaScript qué tipo de datos es nulo, obtenemos una respuesta bastante inequívoca. Sin embargo, aquí no funcionará sin algunos trucos:
let x = null; console.log(typeof(x)); //! , null objet, ? console.log(x instanceof Object.prototype.constructor); //false // ! )
Vale la pena recordar que
null
es un tipo de datos especial, aunque el comienzo del ejemplo anterior apuntaba estrictamente a otro. Para comprender mejor por qué este tipo particular se agregó al lenguaje, me parece que vale la pena explorar los conceptos básicos de la sintaxis de C ++ o C #.
Y, por supuesto, en las entrevistas a menudo uno se encuentra con esa tarea, cuya peculiaridad está relacionada con la escritura dinámica:
console.log(null==undefined);//true console.log(null===undefined);// false
Una gran cantidad de trucos están asociados con la conversión de tipos al comparar en JS; no somos físicamente capaces de traerlos todos aquí. Recomendamos consultar
"Qué demonios JavaScript" .

Características ilógicas que quedan en el lenguaje durante el proceso de desarrollo.
Adición de líneas. De hecho, la adición de cadenas con números no se puede atribuir a errores en el desarrollo del lenguaje, sin embargo, en el contexto de JavaScript, esto condujo a ejemplos bien conocidos que no se consideran lo suficientemente lógicos:
codepen.io/pen/?editors=0011 let x = 15; let y = "15"; console.log(x+y);// "" console.log(xy); //
El hecho de que plus simplemente agregue líneas con números es relativamente ilógico, pero solo necesita recordar esto. Esto puede ser especialmente inusual porque los otros dos lenguajes interpretados que son populares y ampliamente utilizados en el desarrollo web, PHP y Python, no arrojan tales trucos con la adición de cadenas y números y se comportan de manera mucho más predecible en tales operaciones.
Ejemplos similares son menos conocidos, por ejemplo, con NaN:
console.log(NaN == NaN); //false console.log(NaN > NaN); //false console.log(NaN < NaN); //false … ... , NaN? console.log(typeof(NaN)); // number
A menudo, NaN trae sorpresas desagradables si, por ejemplo, configuró incorrectamente la verificación de tipos.
El ejemplo con 0.1 +0.2 es mucho más famoso, porque este error está relacionado con el formato IEEE 754, que también se usa, por ejemplo, en un Python tan "matemático".
También incluimos un error menos conocido con el número Epsilon, la razón por la cual se encuentra en la misma línea:
console.log(0.1+0.2)// 0.30000000000000004 console.log(Number.EPSILON);// 2.220446049250313e-16 console.log(Number.EPSILON + 2.1) // 2.1000000000000005
Y preguntas que son un poco más complicadas:
Object.prototype.toString.call([])// ? // -> '[object Array]' Object.prototype.toString.call(new Date) // Date? // -> '[object Date]'

Etapas de procesamiento de eventos
Muchos principiantes no entienden los eventos del navegador. A menudo, incluso desconocidos son los principios más básicos por los que funcionan los eventos del navegador: intercepción, ascenso y eventos predeterminados. Lo más misterioso desde el punto de vista de un principiante es la aparición de un evento que, sin duda, está justificado al principio y plantea preguntas. Una ventana emergente funciona de la siguiente manera: cuando hace clic en un elemento DOM anidado, el evento se activa no solo en él, sino también en el elemento primario, si también se instaló un controlador con dicho evento en el elemento primario.
En caso de que surja un evento, es posible que debamos cancelarlo.
// , function MouseOn(e){ this.style.color = "red"; e.stopPropagation(); // }
Además, para los principiantes a menudo es un problema cancelar eventos que ocurren de manera predeterminada. Esto es especialmente importante cuando se desarrollan formularios, porque la validación de formularios, por ejemplo, debe hacerse tanto en el lado del cliente como en el lado del servidor:
codepen.io/isakura313/pen/GRKMdaR?editors=0010 document.querySelector(".button-form").addEventListener( 'click', function(e){ e.preventDefault(); console.log(' . , ') } )
Cancelar la aparición de un evento también puede traer algunos problemas: por ejemplo, puede crear una llamada "zona muerta" en la que lo necesario no funcionará, por ejemplo, un evento de un elemento que "no tiene suerte" de estar cerca.
¡Gracias a todos por su atención! Aquí hay algunos enlaces útiles de los que puede extraer mucha información útil:
Eso es todo. Te esperamos en el
seminario web gratuito , que se realizará el 12 de septiembre.