Javascript preguntas entrevista Flashcards

1
Q

Como funciona la propagacion de eventos de javascirpt?

A

La delegación de eventos se basa en el concepto de propagación de eventos (event bubbling), donde un evento se origina en el elemento donde ocurre la acción (por ejemplo, un clic en un botón) y luego se “burbujea” hacia arriba a través del árbol DOM hasta llegar al documento raíz.

Al colocar un solo listener en un contenedor común de varios elementos, podemos identificar cuál de los elementos hijos fue el objetivo real (el elemento clicado, por ejemplo) utilizando la propiedad event.target.

event.target.nodeName
event.target.textContent

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Como funciona el evento this en javascript?

A

En JavaScript, this es una referencia al contexto en el que se ejecuta una función. Su valor depende de cómo y dónde se llame la función, lo que puede llevar a diferentes resultados en distintos contextos.

1-En el contexto global (fuera de cualquier función o clase), this hace referencia al objeto global, que es window en navegadores.

2-Dentro de un método de un objeto, this se refiere al propio objeto. Es útil para acceder a las propiedades y otros métodos del mismo objeto.

3-Cuando this se usa en una función que no pertenece a un objeto, su valor depende del modo en que se llame a la función:

En modo estricto (‘use strict’), this es undefined.

Sin modo estricto, this será el objeto global (como window en el navegador).

4-En funciones flecha, this se determina en el momento en que se define la función y mantiene el contexto en el que fue creada. Esto significa que no cambia, independientemente de cómo o dónde se llame la función.

const person = {
name: “Ana”,
greet: () => {
console.log(Hola, soy ${this.name});
}
};

person.greet(); // Salida: “Hola, soy undefined”

En el ejemplo anterior, this.name es undefined porque las funciones flecha no tienen su propio this. En su lugar, this se hereda del contexto en el que la función fue definida, que en este caso es el contexto global.

5-En el contexto de una clase, this se refiere a la instancia de esa clase.

6-En un event listener, this se refiere al elemento HTML que desencadenó el evento.

En Resumen
En el contexto global: this refiere al objeto global (como window en navegadores).
En métodos de un objeto: this refiere al objeto que contiene el método.
En funciones independientes: depende de cómo se llama y si se usa use strict.
En funciones flecha: this hereda del contexto en el que la función fue creada.
En clases: this refiere a la instancia de la clase.
En event listeners: this refiere al elemento que desencadena el evento.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Explica la difrencia de call, apply y bind

A

const car1 = { brand: “Toyota”, model: “Corolla” };
const car2 = { brand: “Honda”, model: “Civic” };

function describeCar(year, color) {
console.log(Este es un ${year} ${this.brand} ${this.model} de color ${color}.);
}
—————————————————-
// Usando call para invocar describeCar con car1

// Usando apply para invocar describeCar con car2

describeCar.apply(car2, [2021, “azul”]); // Salida: “Este es un 2021 Honda Civic de color azul.”

// Usando bind para crear una nueva función describeToyota

const describeToyota = describeCar.bind(car1, 2022, “negro”);
describeToyota(); // Salida: “Este es un 2022 Toyota Corolla de color negro.”
——————————————————-
Cada uno de estos métodos permite invocar describeCar en un contexto específico (this apunta a car1 o car2) y pasar los argumentos que necesita la función.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Explica como funciona la herencia de los prototipos

A

En JavaScript, la herencia de prototipos permite que los objetos hereden propiedades y métodos de otros objetos. Esto se hace a través de la cadena de prototipos, en la que cada objeto tiene una propiedad interna llamada [[Prototype]] que apunta a otro objeto. Si un objeto necesita acceder a una propiedad o método que no tiene, el motor de JavaScript sube en la cadena de prototipos hasta encontrarla o llegar a null.

EJEMPLO:

  • Creamos la función constructora Animal y le añadimos un método hablar.
    Creamos la función constructora Perro y, dentro de ella, llamamos al constructor Animal usando Animal.call(this, nombre).
    Usamos Object.create para asignar el prototipo de Animal al prototipo de Perro, de manera que Perro hereda de Animal.
    Finalmente, asignamos Perro.prototype.constructor = Perro para que Perro mantenga una referencia correcta a su propio constructor.*
// Función constructora 'Animal'
function Animal(nombre) {
  this.nombre = nombre;
}

// Agregar un método al prototipo de Animal
Animal.prototype.hablar = function() {
  console.log(`${this.nombre} hace un sonido`);
};

// Función constructora 'Perro' que hereda de 'Animal'
function Perro(nombre, raza) {
  // Llamamos al constructor de 'Animal' con 'call'
  Animal.call(this, nombre); // Esto configura 'nombre' para 'Perro'
  this.raza = raza;
}

// Hacer que Perro herede de Animal
Perro.prototype = Object.create(Animal.prototype);
Perro.prototype.constructor = Perro;

// Agregar métodos específicos de Perro
Perro.prototype.ladrar = function() {
  console.log(`${this.nombre} ladra: ¡Guau!`);
};

// Crear instancias
const miPerro = new Perro("Firulais", "Labrador");
miPerro.hablar(); // Salida: "Firulais hace un sonido"
miPerro.ladrar(); // Salida: "Firulais ladra: ¡Guau!"

Desde ES6, JavaScript introdujo la sintaxis de class, que simplifica y aclara el proceso de herencia. Las clases son azucar sintáctico sobre el modelo de herencia de prototipos

EXPLICACION
* Definimos la clase base Animal con un constructor y un método hablar.
* Creamos la clase Perro que hereda de Animal usando extends.
* En el constructor de Perro, usamos super(nombre) para llamar al constructor de Animal, lo cual inicializa nombre.
* Agregamos el método ladrar en Perro para un comportamiento específico de los perros.

EJEMPLO

// Definir la clase 'Animal'
class Animal {
  constructor(nombre) {
    this.nombre = nombre;
  }
  
  hablar() {
    console.log(`${this.nombre} hace un sonido`);
  }
}

// Definir la clase 'Perro' que hereda de 'Animal'
class Perro extends Animal {
  constructor(nombre, raza) {
    super(nombre); // Llamamos al constructor de la clase padre (Animal)
    this.raza = raza;
  }
  
  ladrar() {
    console.log(`${this.nombre} ladra: ¡Guau!`);
  }
}

// Crear instancias
const miPerro = new Perro("Firulais", "Labrador");
miPerro.hablar(); // Salida: "Firulais hace un sonido"
miPerro.ladrar(); // Salida: "Firulais ladra: ¡Guau!"
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Explique la diferencia cuando una variable es: null, undefined o undeclared. Como chequearia cada uno de estos estados?

A

UNDECLARED

Una variable no declarada (undeclared) se crea cuando se asigna un valor a un identificador que no ha sido creado previamente usando var, let o const. Las variables no declaradas se crearan de forma global fuera del contexto actual. En el modo escrito, se creara un ReferenceError cuando se intente asignar un valor a una variable no declarada. Las variables no declaradas son una mala páctica, de la misma forma que las variables globales son una mala práctica.

UNDEFINED

Una variable que es undefined es una variable que ha sido declarada, pero no se le ha asignado un valor. Esta variable es de tipo undefined. Si una función no devuelve un valor especifico, se devolvera por defecto undefined.

Para chequear si una variable es undefined, se utiliza el operador de igualdad estricta(===) o el operador typeof que devolvera la cadena ‘undefined’. Es importante recalcar que no se utiliza el operador de igualdad abstracta (==) ya que este devolverá true si el valor es null.

NULL

Una variable que es null tendra asignado explicitamente el valor null a diferencia de undefined que no se ha asignado ningun valor especifico. Para chequear si una variable es null se utiliza el operador de igualdad estricta ( ===). Es importante recalcar, de la misma forma que anteriormente, no se debe utilizar el operador de igualdad (==) que devolverá true si el valor es undefined.

var foo = null;
console.log(foo === null); // true
console.log(typeof foo === ‘object’); // true

console.log(foo == undefined); // true. Wrong, don’t use this to check!

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Explicame que es sincronismo y asincronismo en javascript

A

En JavaScript, sincronismo y asincronismo determinan cómo se gestionan y ejecutan las operaciones en relación con el ciclo de eventos y el motor de ejecución.

Sincronismo en JavaScript implica que cada instrucción se ejecuta secuencialmente en el "call stack," o pila de ejecución. No se pasa a la siguiente instrucción hasta que la anterior haya concluido, lo cual puede ser restrictivo en el caso de tareas de larga duración, ya que estas bloquean el flujo del programa.

Asincronismo introduce una forma no bloqueante de ejecutar código. JavaScript, a través del event loop, permite iniciar tareas asíncronas, como consultas HTTP o temporizadores, que no requieren procesamiento inmediato en la pila principal. Estas tareas se ejecutan en segundo plano y se vuelven a la pila principal solo cuando están listas para completarse. Mecanismos como callbacks, promises, y async/await son herramientas clave para manejar la asincronía en JavaScript, permitiendo una gestión óptima de tareas sin bloquear el flujo de ejecución principal.

En resumen, el asincronismo en JavaScript permite aprovechar mejor el tiempo y recursos del procesador al no esperar a que se complete cada operación para avanzar a la siguiente, facilitando un flujo de trabajo más eficiente.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Que es un IIFE ?

A

Un IIFE (Immediately Invoked Function Expression) en JavaScript es una función que se declara y se ejecuta inmediatamente después de ser definida. Es útil para crear un ámbito de ejecución aislado, evitando que las variables definidas dentro de él contaminen el ámbito global. La sintaxis básica es:

(function() {
// Código aquí dentro
})();

Desglose:

La función se envuelve en paréntesis (function() { ... }) para que JavaScript la reconozca como una function expression, no como una declaración.
Inmediatamente después, () invoca la función.

Ejemplo:

(function() {
let mensaje = “Este es un IIFE”;
console.log(mensaje); // Salida: Este es un IIFE
})();

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Que es un closure?

A

Un closure es la combinación de una función agrupada (dentro de otra) con referencias a su estado adyacente (el entorno léxico). En otras palabras, un closure te da acceso al alcance de una función externa desde una función interna. En JavaScript, los closure se crean cada vez que se crea una función, en el momento de la creación de la función.

function init() {
var name = “Mozilla”; // name es una variable local creada por init
function displayName() {
// displayName() es la función interna que forma el closure
console.log(name); // usar la variable declarada en la función padre
}
displayName();
}
init();

EJEMPLO 2
function makeFunc() {
const name = “Mozilla”;
function displayName() {
console.log(name);
}
return displayName;
}

const myFunc = makeFunc();
myFunc();

EXPLICACION

Ejecutar este código tiene exactamente el mismo efecto que el ejemplo anterior de la función init() anterior. Lo que es diferente (e interesante) es que la función interna displayName() se devuelve desde la función externa antes de ejecutarse.

A primera vista, puede parecer poco intuitivo que este código siga funcionando. En algunos lenguajes de programación, las variables locales dentro de una función existen solo durante la ejecución de esa función. Una vez que makeFunc() termine de ejecutarse, es de esperar que la variable name ya no sea accesible. Sin embargo, debido a que el código sigue funcionando como se esperaba, este obviamente no es el caso en JavaScript.

La razón es que las funciones en JavaScript forman closures. Un closure es la combinación de una función y el entorno léxico dentro del cual se declaró esa función. Este entorno consiste en cualquier variable local que estuviera dentro del alcance en el momento en que se creó el closure. En este caso, myFunc es una referencia a la instancia de la función displayName que se crea cuando se ejecuta makeFunc. La instancia de displayName mantiene una referencia a su entorno léxico, dentro del cual existe la variable name. Por esta razón, cuando se invoca myFunc, la variable name permanece disponible para su uso, y ‘Mozilla’ se pasa a console.log.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Diferencia de foreach y map?

A
  1. forEachPropósito: Ejecuta una función específica una vez por cada elemento en el array, pero no devuelve un nuevo array. Solo realiza operaciones para cada elemento.
    Retorno: forEach siempre devuelve undefined.
    Uso ideal: Cuando quieres hacer una operación sin modificar ni transformar el array, por ejemplo, imprimir valores o actualizar variables externas.

Ejemplo:

const numeros = [1, 2, 3];
numeros.forEach((numero) => {
console.log(numero * 2); // Salida: 2, 4, 6
});

  1. mapPropósito: Crea un nuevo array aplicando una función a cada elemento del array original. No modifica el array original, sino que devuelve un array nuevo con los resultados.
    Retorno: map devuelve un nuevo array con los resultados de aplicar la función.
    Uso ideal: Cuando quieres transformar cada elemento y obtener un array nuevo con esos cambios.

Ejemplo:

const numeros = [1, 2, 3];
const dobles = numeros.map((numero) => numero * 2);
console.log(dobles); // Salida: [2, 4, 6]

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Explica que es un callback en javascript

A

Un callback en JavaScript es una función que se pasa como argumento a otra función y se ejecuta después de que la función que la recibe haya completado su trabajo. Los callbacks son fundamentales para manejar operaciones asíncronas, como temporizadores, eventos de usuario y solicitudes de red.
¿Cómo funciona un Callback?

En JavaScript, puedes pasar funciones como argumentos a otras funciones porque las funciones son “ciudadanos de primera clase”. Esto significa que pueden almacenarse en variables, pasarse como argumentos y devolverse como valores. Un callback permite especificar una tarea que se ejecutará después de que otra función termine.
Ejemplo básico de Callback

Supongamos que tienes una función que simula la carga de datos y otra función que se ejecuta cuando esa carga termina:

function cargarDatos(callback) {
console.log(“Cargando datos…”);

// Simula un retraso de 2 segundos
setTimeout(() => {
    console.log("Datos cargados");
    callback(); // Ejecuta el callback después de cargar los datos
}, 2000); }

function mostrarDatos() {
console.log(“Mostrando datos en pantalla”);
}

cargarDatos(mostrarDatos);

Explicación

La función cargarDatos simula la carga de datos.
cargarDatos recibe callback como argumento (en este caso, la función mostrarDatos).
Después de simular la carga (usando setTimeout para esperar 2 segundos), se ejecuta callback(), que muestra los datos en la pantalla.

¿Por qué usar Callbacks?

Los callbacks son esenciales para manejar operaciones asíncronas en JavaScript sin detener el flujo de ejecución del programa. Esto es común en:

Consultas a APIs: cuando necesitas esperar una respuesta sin bloquear el navegador.
Eventos de usuario: como clics o entradas de teclado.
Temporizadores: como setTimeout o setInterval.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Explicame una situacion en la que se utilize una funcion anonima

A

Una función anónima en JavaScript es una función que se define sin nombre. Este tipo de funciones es útil en situaciones donde solo se necesita ejecutar una acción en un momento específico, sin la necesidad de reutilizar el código en otras partes.
Ejemplo de uso común: Eventos

Una situación donde se usa frecuentemente una función anónima es en la gestión de eventos. Supongamos que deseas ejecutar una acción cuando un usuario hace clic en un botón, pero no necesitas darle un nombre a la función, ya que probablemente solo se utilizará en ese contexto.

const boton = document.getElementById(“miBoton”);

boton.addEventListener(“click”, function() {
console.log(“El botón fue clickeado”);
});

Aquí, la función que se ejecuta cuando se hace clic en el botón es anónima. Esto es conveniente porque:

No se reutiliza: No planeas usar esta función en otro lugar, por lo que darle un nombre no es necesario.
Código más limpio y directo: Puedes ver la lógica que se ejecuta en el mismo lugar donde defines el evento.

Otros ejemplos de situaciones donde usar funciones anónimas

setTimeout y setInterval: Si necesitas ejecutar una función después de cierto tiempo o repetidamente, puedes usar una función anónima.

setTimeout(function() {
console.log(“Esto se ejecuta después de 2 segundos”);
}, 2000);

Funciones map, forEach, filter: Al procesar arrays, puedes pasar una función anónima para realizar operaciones en cada elemento.

const numeros = [1, 2, 3];
const dobles = numeros.map(function(numero) {
    return numero * 2;
});
console.log(dobles); // Salida: [2, 4, 6]

En estos casos, una función anónima ayuda a mantener el código organizado y reduce la necesidad de nombres innecesarios.J

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

How do you organize your code? (module pattern, classical inheritance?)

A

En el pasado, he utilizado Backbone para mis modelos, lo cual fomenta un enfoque más orientado a objetos (OOP), creando modelos de Backbone y adjuntándoles métodos.

El patrón de módulos sigue siendo excelente, pero hoy en día uso React/Redux, que utiliza un flujo de datos unidireccional basado en la arquitectura Flux. Representaría los modelos de mi aplicación usando objetos simples y escribiría funciones puras de utilidad para manipular estos objetos. El estado se manipula mediante acciones y reducers, como en cualquier otra aplicación de Redux.

Explicación:

Uso de Backbone en el pasado: Con Backbone, se seguía un enfoque de programación orientada a objetos (OOP). En esta metodología, los modelos de datos (las "entidades" de la aplicación) se representaban con instancias de clases de Backbone, y se les añadían métodos para manejar sus propios datos y comportamientos.

Cambio hacia React/Redux: Con React y Redux, la forma de manejar datos es diferente. En lugar de usar clases para crear modelos, ahora se opta por representar los datos de la aplicación como objetos simples de JavaScript. Esto se debe a que Redux utiliza el patrón Flux, donde el flujo de datos es unidireccional (es decir, la información fluye en una sola dirección).

Manipulación del estado: En Redux, el estado de la aplicación no se modifica directamente. En su lugar:
    Se crean acciones (actions) para definir qué tipo de cambio debe ocurrir en el estado.
    Los reducers son funciones puras que toman el estado actual y una acción, y devuelven un nuevo estado basado en esa acción.

Uso de funciones puras: Para manipular los datos, en lugar de métodos en los modelos (como en Backbone), se emplean funciones puras de utilidad. Estas funciones reciben los datos como parámetros, los transforman y devuelven los datos modificados sin alterar los originales, lo que ayuda a mantener la inmutabilidad del estado en Redux.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What’s the difference between host objects and native objects?

A

Native objects are objects that are part of the JavaScript language defined by the ECMAScript specification, such as String, Math, RegExp, Object, Function, etc.

Host objects are provided by the runtime environment (browser or Node), such as window, XMLHTTPRequest, etc

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Difference between: function Person(){}, var person = Person(), and var person = new Person()?

A

This question is pretty vague. My best guess at its intention is that it is asking about constructors in JavaScript. Technically speaking, function Person(){} is just a normal function declaration. The convention is to use PascalCase for functions that are intended to be used as constructors.

var person = Person() invokes the Person as a function, and not as a constructor. Invoking as such is a common mistake if the function is intended to be used as a constructor. Typically, the constructor does not return anything, hence invoking the constructor like a normal function will return undefined and that gets assigned to the variable intended as the instance.

var person = new Person() creates an instance of the Person object using the new operator, which inherits from Person.prototype. An alternative would be to use Object.create, such as: Object.create(Person.prototype).

function Person(name) {
this.name = name;
}

var person = Person(‘John’);
console.log(person); // undefined
console.log(person.name); // Uncaught TypeError: Cannot read property ‘name’ of undefined

var person = new Person(‘John’);
console.log(person); // Person { name: “John” }
console.log(person.name); // “john”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Que es y como funciona el operador new?

A

El operador new en JavaScript se utiliza para crear una nueva instancia de un objeto a partir de una función constructora. Este operador es clave en la programación orientada a objetos (OOP) en JavaScript, ya que permite crear instancias de “clases” (que en JavaScript se definen mediante funciones constructoras) y asociar propiedades y métodos a estos objetos.
¿Cómo funciona el operador new?

Cuando utilizas el operador new para crear una instancia, sucede lo siguiente:

Creación de un nuevo objeto vacío: Se crea un nuevo objeto vacío {}.

Enlace del prototipo: El nuevo objeto se asocia con el prototipo de la función constructora, lo que significa que el objeto heredará métodos y propiedades definidas en el prototipo de esa función.

Ejecución de la función constructora: La función constructora se ejecuta con el objeto recién creado como su contexto (this). Dentro de esta función, puedes asignar propiedades y métodos al objeto.

Retorno del objeto: Si la función constructora no devuelve explícitamente un objeto, el nuevo objeto creado se devuelve por defecto. Si la función constructora devuelve un objeto, ese objeto será el que se devuelva en lugar del objeto creado por new.

Ejemplo básico:

// Función constructora
function Persona(nombre, edad) {
this.nombre = nombre;
this.edad = edad;
}

// Usando el operador new
const juan = new Persona(‘Juan’, 30);

console.log(juan.nombre); // “Juan”
console.log(juan.edad); // 30

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What’s the difference between feature detection, feature inference, and using the UA string?

A

Feature Detection: Verificas directamente si una característica está soportada.
if (‘flex’ in document.body.style) {
// Implementa el diseño de flexbox
} else {
// Usa un diseño alternativo
}
Feature Inference: Asumes que el soporte de una característica implica el soporte de otras.
if (‘querySelector’ in document) {
// Se supone que el navegador soporta otros métodos modernos
}
User-Agent String: Usas la cadena del User-Agent para inferir el navegador o el dispositivo.
const userAgent = navigator.userAgent;
if (userAgent.includes(“Chrome”)) {
// Especifica opciones para Chrome
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Explain Ajax in as much detail as possible.

A

AJAX (Asynchronous JavaScript and XML)

AJAX (Asynchronous JavaScript and XML) es una técnica en JavaScript que permite a las aplicaciones web hacer peticiones al servidor para obtener datos sin necesidad de recargar toda la página. Se basa en el uso del objeto XMLHttpRequest o de la API fetch moderna para enviar y recibir datos de manera asíncrona.

Cuando se hace una solicitud AJAX, el navegador envía una petición HTTP al servidor, pero el flujo de la aplicación web no se detiene. Esto es posible gracias a que AJAX es asíncrono, lo cual significa que el código sigue ejecutándose mientras se espera la respuesta del servidor. Cuando el servidor responde, la aplicación recibe esos datos y los usa para actualizar solo ciertas partes de la página, ofreciendo una experiencia más fluida y rápida al usuario.

fetch(‘https://api.example.com/data’)
.then(response => response.json()) // Procesa la respuesta en formato JSON
.then(data => {
console.log(data); // Utiliza los datos recibidos sin recargar la página
})
.catch(error => console.error(‘Error:’, error));

En resumen, AJAX permite que las aplicaciones web interactúen con el servidor para actualizar la información en la página de manera dinámica, sin necesidad de una recarga completa.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

What are the advantages and disadvantages of using Ajax?

A

ventajas y desventajas de AJAX de manera técnica:

Ventajas:

Mayor rapidez y rendimiento: AJAX permite actualizar solo las partes necesarias de una página, en lugar de recargar toda la página web. Esto reduce el tiempo de carga y ahorra ancho de banda, resultando en una experiencia de usuario más fluida y eficiente.

Experiencia de usuario mejorada: Gracias a su naturaleza asíncrona, AJAX permite a los usuarios interactuar con otras partes de la página mientras esperan que el servidor responda. Esto significa menos interrupciones y una navegación más dinámica.

Interacción en tiempo real: AJAX es ideal para aplicaciones en las que se necesita interactuar en tiempo real, como en chats, notificaciones en redes sociales o recomendaciones de búsqueda en tiempo real.

Desventajas:

Problemas de accesibilidad y SEO: Debido a que AJAX carga contenido de forma dinámica, es posible que algunos motores de búsqueda y tecnologías de asistencia (como lectores de pantalla) no detecten el contenido correctamente, lo cual afecta el SEO y la accesibilidad.

Dependencia de JavaScript y conexión a internet: Si el usuario tiene JavaScript deshabilitado o una mala conexión a internet, las funcionalidades basadas en AJAX pueden fallar o no ejecutarse correctamente.

Historial de navegación limitado: Como AJAX no recarga la página, los cambios dinámicos no se guardan en el historial de navegación. Esto puede dificultar la navegación "atrás" del usuario, lo que puede ser confuso o frustrante si el usuario pierde el contexto de dónde estaba en la aplicación.

En resumen, AJAX mejora la experiencia de usuario y la eficiencia de carga, pero puede tener limitaciones en accesibilidad, SEO y manejo del historial.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Explain how JSONP works (and how it’s not really Ajax)

A

Explicación

JSONP (JSON with Padding) es una técnica que permite hacer solicitudes de datos entre distintos dominios. AJAX, por diseño, tiene restricciones de seguridad conocidas como “same-origin policy”, que solo permiten que las solicitudes se hagan al mismo dominio de la página web. JSONP se desarrolló como una solución alternativa para superar estas limitaciones en los navegadores.

A diferencia de AJAX, que utiliza XMLHttpRequest o fetch, JSONP funciona a través de etiquetas

 que permiten cargar contenido de otros dominios, ya que los navegadores no bloquean el acceso a archivos JavaScript externos. El servidor envía los datos dentro de una función de JavaScript, que se "llama" automáticamente cuando el archivo se carga en el navegador.
Ejemplo de funcionamiento de JSONP

Imagina que quieres obtener datos de un servidor en otro dominio (por ejemplo, https://api.ejemplo.com/data). En lugar de hacer una solicitud AJAX normal, el navegador crea una etiqueta

 que apunta a esa URL. La respuesta del servidor no es un simple JSON; en su lugar, el servidor envía una función con el JSON dentro, algo como esto:

callback({ “nombre”: “Juan”, “edad”: 30 });

Y en el código del cliente, defines callback para que se ejecute cuando la respuesta llegue. Al recibir la respuesta, esta función se ejecuta, y los datos pueden ser procesados sin errores de restricción de dominio.
Diferencias clave entre JSONP y AJAX

Transporte: AJAX usa XMLHttpRequest o fetch, mientras que JSONP usa etiquetas <script>.
Seguridad: AJAX tiene restricciones de "same-origin policy", mientras que JSONP evita esta limitación pero abre una puerta a posibles riesgos de seguridad, ya que ejecuta directamente el código de otro dominio.
No es realmente AJAX: JSONP no es asíncrono en el sentido de AJAX; utiliza una técnica alternativa para obtener datos, sin hacer una llamada XMLHttpRequest.

Resumen

JSONP permite cargar datos de otros dominios en un navegador de manera segura en su época, aunque actualmente los desarrolladores prefieren soluciones más modernas y seguras, como CORS (Cross-Origin Resource Sharing), en lugar de JSONP.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Que son plantillas en javascript?

A

JavaScript templating es una técnica que permite crear plantillas de HTML dinámicas y reutilizables usando JavaScript. En lugar de escribir el HTML completo con todos sus datos, se usan “plantillas” que contienen un diseño base y “placeholders” o variables que se reemplazan con datos dinámicos cuando la página se renderiza. Esto es muy útil en aplicaciones web, donde se quiere mostrar datos que cambian constantemente, como en listas de productos, comentarios de usuarios o noticias.
Explicación sencilla

Imagina que tienes una tarjeta para mostrar información de productos. En vez de escribir el HTML completo para cada producto, usas una plantilla que tiene un diseño básico. Luego, llenas esa plantilla con los datos de cada producto específico, como el nombre y el precio. JavaScript toma la plantilla, la copia y reemplaza los espacios en blanco con los datos correctos.
Ejemplo de cómo funciona JavaScript templating

Supongamos que quieres crear una lista de productos con nombre y precio. Puedes usar una plantilla que tenga el formato básico de cada producto y luego, usando JavaScript, reemplazar las partes necesarias.

Ejemplo de plantilla usando “template literals”:

// Datos de ejemplo
const productos = [
{ nombre: “Camiseta”, precio: “$20” },
{ nombre: “Pantalón”, precio: “$40” },
];

// Plantilla en JavaScript
function crearPlantilla(producto) {
return `
<div class="producto">
<h2>${producto.nombre}</h2>
<p>Precio: ${producto.precio}</p>
</div>
`;
}

// Genera el HTML final
let html = ‘’;
productos.forEach(producto => {
html += crearPlantilla(producto);
});

// Inserta el HTML en el DOM
document.getElementById(“contenedor-productos”).innerHTML = html;

En este ejemplo, crearPlantilla es una función que toma un objeto de producto y devuelve un bloque de HTML con los datos de ese producto. Luego, se genera el HTML para todos los productos y se inserta en la página.
Ventajas de usar JavaScript templating

Reutilización de código: Se puede usar la misma plantilla para distintos datos sin escribir HTML varias veces.
Facilidad de mantenimiento: Si quieres cambiar el diseño, solo tienes que actualizar la plantilla, y el cambio se reflejará en todas partes.
Separación de lógica y diseño: Facilita mantener el código organizado al separar la lógica de la aplicación de la estructura HTML.

Librerías de JavaScript templating

Además de crear plantillas de manera nativa (como en el ejemplo), existen librerías como Handlebars.js, Mustache.js y frameworks como Vue.js o React que permiten crear plantillas más potentes y con características avanzadas, facilitando la creación de aplicaciones complejas.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Como funciona el hoisting en javascript

A

Hoisting en JavaScript es un comportamiento del lenguaje donde las declaraciones de variables y funciones se “elevan” al inicio de su contexto de ejecución (como una función o el script global), antes de que el código realmente se ejecute. Esto significa que puedes usar variables y funciones en el código antes de haberlas declarado explícitamente en líneas anteriores, aunque el comportamiento exacto depende de cómo se haya hecho la declaración.
Ejemplo de hoisting en funciones

Cuando declaras una función con la palabra clave function, la función completa se “eleva” o “sube” al inicio del contexto. Esto permite llamarla antes de su declaración.

saludar(); // Esto funciona por hoisting y muestra “¡Hola!”

function saludar() {
console.log(“¡Hola!”);
}

Ejemplo de hoisting en variables

Con las variables, el comportamiento varía según cómo se declaran. JavaScript hace “hoisting” de las declaraciones de variables, pero no de sus asignaciones de valor.
Variables declaradas con var

Si declaras una variable con var, JavaScript eleva solo la declaración (no el valor asignado), inicializándola como undefined al principio del contexto. Esto significa que puedes hacer referencia a la variable antes de su declaración, pero su valor será undefined hasta que se asigne.

console.log(nombre); // Muestra undefined debido al hoisting

var nombre = “Juan”;
console.log(nombre); // Muestra “Juan”

Variables declaradas con let y const

Las variables declaradas con let y const también se “elevan”, pero se colocan en un “temporal dead zone” (zona muerta temporal). Esto significa que, aunque se hace hoisting de la declaración, no pueden usarse antes de la línea en la que se declaran y lanzarán un error si intentas acceder a ellas.

console.log(apellido); // Error: Cannot access ‘apellido’ before initialization

let apellido = “Pérez”;
console.log(apellido); // Muestra “Pérez”

Resumen

Funciones: La declaración completa se eleva al inicio del contexto, por lo que puedes llamarlas antes de declararlas.
Variables con var: Solo la declaración se eleva; se inicializan como undefined, y la asignación se hace en su lugar original.
Variables con let y const: La declaración se eleva, pero no pueden usarse antes de su línea de declaración, lanzando un error si se intenta.

Hoisting ayuda a entender cómo JavaScript organiza el código internamente y cómo se deben declarar y utilizar variables y funciones para evitar errores o comportamientos inesperados.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Que es el event bubbling

A

¿Qué es “event bubbling”?

Event bubbling (o propagación de eventos en “burbujeo”) es un mecanismo en JavaScript que se usa para controlar cómo los eventos se transmiten a través de los elementos del DOM. Cuando ocurre un evento (como un clic) en un elemento dentro de otro elemento, el evento se mueve o “burbujea” desde el elemento donde ocurrió inicialmente hacia sus elementos padres. Esto significa que el evento va subiendo en la jerarquía del DOM desde el elemento más específico hasta el más general, llegando hasta el document.
Ejemplo sencillo

Imagina que tienes un botón (<button>) dentro de un div dentro de otro div. Si haces clic en el botón, el evento click primero se activará en el botón, luego en el div que lo contiene, luego en el siguiente div más externo, y así sucesivamente, hasta llegar al document.</button>

<div>
<div>
<button>¡Haz clic aquí!</button>
</div>
</div>

Código de ejemplo con event bubbling

Si añadimos escuchadores de eventos (event listeners) en cada elemento, puedes observar el comportamiento de burbujeo:

document.getElementById(“boton”).addEventListener(“click”, () => {
console.log(“Botón fue clickeado”);
});

document.getElementById(“contenedor-interno”).addEventListener(“click”, () => {
console.log(“Contenedor interno fue clickeado”);
});

document.getElementById(“contenedor-externo”).addEventListener(“click”, () => {
console.log(“Contenedor externo fue clickeado”);
});

Al hacer clic en el botón, la consola mostrará:

"Botón fue clickeado"
"Contenedor interno fue clickeado"
"Contenedor externo fue clickeado"

Esto muestra cómo el evento de clic “burbujea” hacia arriba.
¿Por qué es útil event bubbling?

Event bubbling permite capturar eventos en un elemento padre en lugar de cada uno de sus elementos hijos. Esto puede hacer que el código sea más eficiente, ya que puedes manejar eventos para varios elementos desde un solo lugar. Por ejemplo, en vez de añadir un evento de clic a cada botón dentro de un div, puedes añadirlo al div mismo y usar la información del evento para ver qué botón fue clickeado.
Cómo detener el bubbling

Si quieres evitar que un evento siga propagándose hacia los elementos padres, puedes usar event.stopPropagation():

document.getElementById(“boton”).addEventListener(“click”, (event) => {
console.log(“Botón fue clickeado”);
event.stopPropagation(); // Detiene la propagación
});

Esto evita que el evento suba a los contenedores, y solo se ejecutará el código asociado al botón.
Resumen

Event bubbling es la propagación de eventos hacia arriba en la jerarquía del DOM. Es útil para manejar eventos de manera eficiente, pero se puede detener con event.stopPropagation() si no quieres que el evento suba por los elementos padres.

ChatGPT puede cometer errores. Comprueba la informació

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Diferencia entre atributo y propiedad en javascript?

A

En JavaScript y en el DOM, attribute y property son conceptos relacionados pero distintos cuando se trabaja con elementos HTML. Aquí te explico sus diferencias:
1. Attribute (Atributo)

Un attribute es lo que está escrito directamente en el HTML y se define en el marcado del elemento. Representa la configuración inicial del elemento en el documento HTML y siempre es una cadena de texto (string), independientemente del tipo de dato que almacene.

Ejemplo de atributo en HTML:

<input></input>

En este caso, id, type y value son atributos del elemento <input></input>. Estos son los valores iniciales que se cargan al renderizar el HTML en el navegador.

Para acceder o modificar un atributo en JavaScript, usamos métodos como getAttribute y setAttribute.

const input = document.getElementById(“nombre”);
console.log(input.getAttribute(“value”)); // “Juan”
input.setAttribute(“value”, “Carlos”);

  1. Property (Propiedad)

Una property es una propiedad del objeto DOM en JavaScript que representa el elemento HTML. Cuando el navegador interpreta el HTML y construye el DOM, los atributos iniciales del HTML se convierten en propiedades de los elementos. Sin embargo, las propiedades pueden cambiar durante la ejecución de la aplicación y no necesariamente reflejan el valor de los atributos originales en el HTML.

Las propiedades también pueden tener distintos tipos de datos, como booleanos, números u objetos, y no se limitan a cadenas de texto.

Ejemplo de propiedad en JavaScript:

console.log(input.value); // “Juan”
input.value = “Carlos”;
console.log(input.value); // “Carlos”

Aquí, value es una propiedad de input y refleja el valor actual del elemento, que puede haber cambiado a través de interacciones o código JavaScript.
Diferencias clave entre attribute y property

Origen y actualización: Los atributos son parte del HTML original, mientras que las propiedades pertenecen al DOM y pueden actualizarse dinámicamente durante la ejecución.
Tipos de datos: Los atributos siempre son cadenas de texto, pero las propiedades pueden tener otros tipos de datos.
Sincronización: En algunos casos, los valores de los atributos y las propiedades son iguales al principio, pero luego pueden desincronizarse si cambian en el DOM.

Ejemplo de desincronización

<input></input>

const checkbox = document.getElementById(“check”);
console.log(checkbox.getAttribute(“checked”)); // “checked” (atributo inicial)
console.log(checkbox.checked); // true (propiedad inicial)

checkbox.checked = false; // Cambia la propiedad, no el atributo
console.log(checkbox.getAttribute(“checked”)); // “checked” (sin cambio)
console.log(checkbox.checked); // false (cambio en la propiedad)

En este caso, el atributo checked sigue igual, pero la propiedad checked refleja el estado actual del checkbox en el DOM.
Resumen

Attribute: Configuración inicial del elemento en el HTML. Se accede con getAttribute y setAttribute.
Property: Representa el estado actual del elemento en el DOM y puede cambiar dinámicamente. Se accede directamente como propiedad del objeto en JavaScript.

Las propiedades reflejan el estado actual del elemento en el DOM, mientras que los atributos representan la configuración inicial en el HTML.

ChatGPT puede cometer errores. Comprueba la inform

24
Q

Porque no es buena idea modificar objetos nativos de javascript?

A

Extender objetos integrados en JavaScript puede causar conflictos de nombres, problemas de rendimiento, dificultad en el mantenimiento del código y posibles problemas de compatibilidad. Es preferible crear funciones o clases independientes en lugar de modificar la funcionalidad base del lenguaje.

25
Q

Diferencia entre el evento load y DOMContentLoaded

A

Explicación

En JavaScript, el navegador proporciona dos eventos principales para detectar cuándo una página web ha terminado de cargarse: DOMContentLoaded y load. Aunque ambos indican diferentes momentos en los que se ha cargado la página, tienen propósitos distintos.
1. DOMContentLoaded

El evento DOMContentLoaded se dispara cuando el HTML ha sido completamente cargado y analizado, es decir, cuando la estructura básica de la página (el DOM) está lista para ser manipulada por JavaScript. Sin embargo, no espera a que se carguen recursos externos, como imágenes, videos, o archivos CSS.

Este evento es útil si deseas manipular el contenido HTML de la página tan pronto como sea posible, sin esperar a que todos los recursos externos terminen de cargar.

Ejemplo:

document.addEventListener(“DOMContentLoaded”, () => {
console.log(“El DOM está listo para ser manipulado”);
});

  1. load

El evento load se dispara solo cuando toda la página, incluidos todos los recursos externos (imágenes, estilos CSS, videos, iframes), ha terminado de cargarse completamente. Este evento ocurre después de DOMContentLoaded.

Este evento es más adecuado para situaciones en las que necesitas asegurarte de que todos los elementos visuales y recursos de la página se han cargado antes de interactuar con ellos (por ejemplo, ajustar imágenes o acceder a estilos específicos).

Ejemplo:

window.addEventListener(“load”, () => {
console.log(“Toda la página y sus recursos están completamente cargados”);
});

Diferencias clave entre DOMContentLoaded y load

Momento en que se disparan:
    DOMContentLoaded se dispara cuando solo el HTML y el DOM están completamente cargados.
    load se dispara después de que todos los recursos externos han terminado de cargar.

Uso recomendado:
    Usa DOMContentLoaded si solo necesitas manipular el DOM y no dependes de los recursos externos.
    Usa load si necesitas asegurarte de que todos los recursos de la página están listos antes de ejecutar tu código.

Ejemplo práctico de comparación

document.addEventListener(“DOMContentLoaded”, () => {
console.log(“El DOM está listo, pero no todos los recursos externos pueden estar cargados”);
});

window.addEventListener(“load”, () => {
console.log(“Todos los recursos externos han terminado de cargar”);
});

Al ejecutar este código en una página con imágenes pesadas o videos, DOMContentLoaded se ejecutará primero, seguido de load cuando todos los recursos externos hayan terminado de cargarse.
Resumen

DOMContentLoaded: Se dispara cuando el HTML está completamente cargado y el DOM está listo para ser manipulado, sin esperar a los recursos externos.
load: Se dispara cuando toda la página, incluidos los recursos externos, ha terminado de cargarse.
26
Q

What is the difference between == and ===?

A

== is the abstract equality operator while === is the strict equality operator. The == operator will compare for equality after doing any necessary type conversions. The === operator will not do type conversion, so if two values are not the same type === will simply return false. When using ==, funky things can happen, such as:

1 == ‘1’; // true
1 == [1]; // true
1 == true; // true
0 == ‘’; // true
0 == ‘0’; // true
0 == false; // true

My advice is never to use the == operator, except for convenience when comparing against null or undefined, where a == null will return true if a is null or undefined.

var a = null;
console.log(a == null); // true
console.log(a == undefined); // true

27
Q

Que es la politica del mismo origen

A

Explicación de la política de mismo origen (same-origin policy) con respecto a JavaScript
¿Qué es la política de mismo origen?

La política de mismo origen es una medida de seguridad implementada por los navegadores web para restringir cómo los documentos o scripts cargados desde un origen pueden interactuar con recursos de otro origen. En otras palabras, esta política impide que un script de una página web acceda o manipule el contenido de otra página web que proviene de un origen diferente.

El origen se define como la combinación de tres componentes:

Protocolo: http, https, ftp, etc.
Dominio: example.com, miweb.com, etc.
Puerto: 80, 443, etc. (si no se especifica, se asume el puerto predeterminado para el protocolo).

Ejemplo sencillo

Imagina que tienes dos páginas web:

https://miweb.com/pagina1
https://otraweb.com/pagina2

Si una página de miweb.com intenta hacer una solicitud JavaScript a otraweb.com (por ejemplo, usando fetch o XMLHttpRequest), el navegador bloquearía esta solicitud debido a la política de mismo origen, ya que ambos dominios son diferentes.
¿Por qué se implementa la política de mismo origen?

La política de mismo origen se diseñó para prevenir ataques de seguridad, como el cross-site scripting (XSS) y el cross-site request forgery (CSRF), que podrían permitir a un sitio malicioso interactuar con recursos de otro sitio sin autorización. Esto garantiza que un sitio web solo pueda acceder a sus propios datos y no pueda robar información de otros sitios web.
¿Cuándo se aplica?

La política de mismo origen afecta principalmente a las siguientes operaciones:

Acceso a cookies: Un script de un origen no puede acceder a las cookies de otro origen.
Acceso a datos del DOM: Un script de un origen no puede leer o modificar el contenido de un iframe o ventana que proviene de un origen diferente.
Solicitudes HTTP: Un script de un origen no puede hacer solicitudes de red (por ejemplo, usando fetch o XMLHttpRequest) a otro origen sin restricciones.

Soluciones y excepciones

Aunque la política de mismo origen es importante para la seguridad, a veces se necesita que un sitio web haga solicitudes a otro dominio (por ejemplo, para obtener datos de una API externa). Aquí es donde entran en juego soluciones como:

CORS (Cross-Origin Resource Sharing): CORS es un mecanismo que permite que los servidores de otros orígenes autoricen las solicitudes de ciertos dominios. Esto se hace mediante el envío de cabeceras HTTP específicas que indican que el recurso puede ser accedido desde un origen diferente.

Ejemplo de cabecera CORS en el servidor:

Access-Control-Allow-Origin: https://miweb.com

JSONP (JSON with Padding): Aunque está obsoleto, JSONP es una técnica que se usaba para hacer solicitudes GET entre dominios diferentes. Sin embargo, esta técnica tiene muchas limitaciones y problemas de seguridad, por lo que hoy en día se prefiere CORS.

PostMessage: Si tienes un iframe de un origen diferente, puedes usar window.postMessage() para enviar mensajes de manera segura entre el padre y el iframe.

Resumen

La política de mismo origen en JavaScript es una medida de seguridad que impide que un sitio web interactúe con recursos de otro dominio sin permiso. Esto ayuda a proteger a los usuarios de ataques de seguridad como el XSS y el CSRF. Sin embargo, existen mecanismos como CORS y PostMessage para permitir que ciertos intercambios de datos entre diferentes orígenes se realicen de manera controlada y segura.

28
Q

Que es una operacion ternaria?

A

La palabra “Ternary” en inglés se refiere a “ternario”, que significa “compuesto de tres elementos”. En programación, una expresión ternaria es una expresión que utiliza tres partes o componentes. Este tipo de expresión en muchos lenguajes de programación se usa para simplificar decisiones simples, en lugar de escribir una estructura if-else completa.
Estructura de una Expresión Ternaria

La estructura básica es:

condición ? valor_si_verdadero : valor_si_falso;

Aquí:

condición es la primera parte y evalúa a true o false.
valor_si_verdadero es el valor que se devuelve si la condición es verdadera.
valor_si_falso es el valor que se devuelve si la condición es falsa.

Ejemplo Simple en JavaScript

Supongamos que queremos comprobar si un número es positivo o negativo y devolver un mensaje correspondiente:

let numero = 5;
let mensaje = numero >= 0 ? “Positivo” : “Negativo”;
console.log(mensaje); // Salida: “Positivo”

En este caso:

La condición es numero >= 0.
El valor_si_verdadero es "Positivo".
El valor_si_falso es "Negativo".

Esta expresión ternaria devuelve “Positivo” si el número es mayor o igual a 0, y “Negativo” si es menor.

29
Q

Que es la directiva “use strict” en javascript

A

“use strict”; es una directiva en JavaScript que activa el “modo estricto” en el código. Al usar “use strict”;, el intérprete de JavaScript aplica reglas más estrictas y evita ciertos errores comunes. Esto ayuda a escribir un código más seguro y con menos errores.
Ventajas de Usar “use strict”;

Evita errores silenciosos: En modo estricto, JavaScript arroja errores donde normalmente ignoraría ciertos problemas, ayudando a detectar errores de programación. Por ejemplo:
    Intentar usar una variable no declarada lanzará un error en lugar de crearla automáticamente en el ámbito global.

Mejora el rendimiento: Algunos motores de JavaScript pueden optimizar el código más eficientemente en modo estricto, ya que se eliminan algunas funciones que podrían ser lentas o difíciles de optimizar.

Evita el uso de palabras reservadas: En modo estricto, se evita el uso accidental de palabras reservadas en el código, como let, class, o super, que son parte del estándar de JavaScript.

Previene malas prácticas: Desactiva características de JavaScript que pueden generar confusión o malentendidos, como la eliminación del with statement.

Desventajas de Usar “use strict”;

Código menos flexible: Para desarrolladores acostumbrados a JavaScript sin modo estricto, puede ser incómodo adaptarse a estas reglas más estrictas.
Posibles errores adicionales: En proyectos grandes, activar "use strict"; sin revisar el código puede llevar a múltiples errores que no existían antes debido a la verificación de variables y el uso de ciertas características.
Incompatibilidad con librerías antiguas: Algunas librerías antiguas no funcionan bien en modo estricto, lo que podría causar problemas de compatibilidad.

Ejemplo con y sin “use strict”;

Sin “use strict”;, el siguiente código funciona pero es propenso a errores:

nombre = “Juan”; // Variable no declarada, crea una variable global
console.log(nombre); // Salida: “Juan”

Con “use strict”;, arroja un error porque no declaramos la variable nombre explícitamente:

“use strict”;
nombre = “Juan”; // Error: nombre is not defined

En este caso, “use strict”; nos ayuda a evitar un posible error, forzándonos a declarar la variable antes de usarla, como let nombre = “Juan”;.

30
Q

Resuelve el problema de fizzbuzz

A

for (let i = 1; i <= 100; i++) {
let f = i % 3 == 0,
b = i % 5 == 0;
console.log(f ? (b ? ‘FizzBuzz’ : ‘Fizz’) : b ? ‘Buzz’ : i);
}

I would not advise you to write the above during interviews though. Just stick with the long but clear approach. For more wacky versions of FizzBuzz, check out the reference link below.

for (var i=1; i <= 20; i++)
{
if (i % 15 == 0)
console.log(“FizzBuzz”);
else if (i % 3 == 0)
console.log(“Fizz”);
else if (i % 5 == 0)
console.log(“Buzz”);
else
console.log(i);
}

for (let i = 1; i <= n; i++) {
console.log((i % 3 ? ‘’ : ‘Fizz’) + (i % 5 ? ‘’ : ‘Buzz’) || i)
}

31
Q

Porque no es recomendable modificar el scope global?

A

En general, es una buena práctica no modificar el ámbito global (global scope) de un sitio web. El ámbito global es donde se almacenan las variables y funciones accesibles desde cualquier parte del código. Hacer cambios aquí puede traer problemas y errores inesperados. Aquí te explico por qué:
Razones para No Modificar el Ámbito Global

Evitar conflictos de nombres: En el ámbito global, todas las variables y funciones están disponibles para cualquier archivo o script en la página. Si creamos variables globales, existe el riesgo de que se sobrescriban entre ellas o con otras variables de librerías externas, lo cual causa errores difíciles de detectar.

Ejemplo: Si llamamos a una variable global usuario y otra librería usa usuario, podríamos sobrescribir su valor sin querer.

Dificultad en depuración: Cuantas más variables existan en el ámbito global, más complejo es rastrear errores. Si algo falla, puede ser difícil encontrar cuál variable está causando el problema debido a que cualquier parte del código podría estar modificándola.

Pérdida de rendimiento: Al tener muchas variables globales, el navegador tarda más en buscar y procesar las variables, especialmente en proyectos grandes. Esto puede hacer que el sitio sea menos eficiente y más lento.

Seguridad y encapsulación: En JavaScript, mantener las variables y funciones dentro de un ámbito (scope) específico es una buena práctica para proteger los datos. Si declaramos todo en el ámbito global, se hace más fácil que otras partes del código (o scripts maliciosos) accedan y modifiquen esas variables.

Ejemplo de Buenas Prácticas con Ámbitos Locales

Una alternativa es usar funciones o módulos para encapsular el código:

(function() {
let mensaje = “Hola, soy local”; // Esta variable no está en el ámbito global
console.log(mensaje);
})();

Aquí, mensaje es local a la función y no interfiere con el ámbito global. Así, evitamos posibles conflictos y mejoramos la seguridad del código.
Resumen

Modificar el ámbito global puede causar problemas de rendimiento, seguridad y conflictos de nombres. Es una buena práctica limitar las variables y funciones globales, usando estructuras de código encapsuladas como funciones o módulos.

ChatGPT puede co

32
Q

Explica que es una pagina web tipo SPA y como es buena para el SEO

A

Una Single Page Application (SPA) es una aplicación web que carga una sola página HTML y actualiza dinámicamente su contenido a medida que el usuario interactúa, sin necesidad de recargar toda la página desde el servidor. Esto se logra mediante JavaScript, proporcionando una experiencia de usuario rápida y fluida.
Ventajas de una SPA

Navegación rápida: Al actualizar solo el contenido necesario sin recargar la página completa, se reduce el tiempo de espera y mejora la experiencia de usuario.
Interactividad similar a una app: Permite crear interfaces muy interactivas, con una experiencia más fluida y moderna.

Desventajas de una SPA

SEO limitado: Como las SPA dependen de JavaScript para cargar contenido, los motores de búsqueda a veces no pueden indexar correctamente las páginas, lo que puede afectar la visibilidad en búsquedas.
Rendimiento inicial: Cargar toda la lógica de la SPA en una sola solicitud puede hacer que el tiempo de carga inicial sea más largo.

Cómo Hacer una SPA Amigable para el SEO

Existen varias prácticas para mejorar el SEO de una SPA:

Renderizado en el servidor (SSR): Con el SSR, el contenido se genera en el servidor y se envía como HTML completo al navegador. Esto permite que los motores de búsqueda indexen el contenido sin depender de JavaScript. Frameworks como Next.js para React y Nuxt.js para Vue facilitan el SSR.

Pre-renderizado: Este método genera versiones HTML estáticas de las páginas de una SPA antes de servirlas, lo que permite que los motores de búsqueda accedan al contenido sin necesidad de ejecutar JavaScript. Es ideal para contenido que cambia poco.

URLs amigables: Utilizar URLs descriptivas y configurarlas para cada sección importante ayuda a los motores de búsqueda a indexar cada sección. Esto se logra con librerías de rutas como React Router o Vue Router.

Meta tags dinámicas: Las etiquetas meta (<title>, <meta description>) son esenciales para el SEO. Usa herramientas como React Helmet para actualizar estas etiquetas en cada sección de la SPA y facilitar que los motores de búsqueda identifiquen el contenido.

Implementar datos estructurados (JSON-LD): Los datos estructurados ayudan a los motores de búsqueda a entender mejor el contenido de la página y pueden mejorar la visibilidad en los resultados de búsqueda.

Manejo de errores 404 y redirecciones: Al manejar adecuadamente errores y redirecciones, se garantiza que los motores de búsqueda interpreten correctamente las rutas de la SPA y se evita el contenido duplicado.

Resumen

Hacer una SPA amigable para SEO implica utilizar técnicas como el renderizado en el servidor, pre-renderizado y gestión de rutas amigables. Además, manejar correctamente las meta tags y los datos estructurados permite que los motores de búsqueda indexen el contenido correctamente, mejorando la visibilidad de la SPA en los resultados de búsqueda.

33
Q

“¿Cuál es el alcance de tu experiencia con Promises y/o sus polyfills?”

A

La pregunta “What is the extent of your experience with Promises and/or their polyfills?” se traduce como:
“¿Cuál es el alcance de tu experiencia con Promises y/o sus polyfills?”
Explicación
¿Qué son las Promises en JavaScript?

Las Promises son una forma de manejar operaciones asíncronas en JavaScript. Una Promise representa un valor que estará disponible ahora, en el futuro, o nunca. Esto ayuda a evitar problemas con callbacks anidados (también conocidos como “callback hell”).

Una Promise tiene tres estados:

Pending (pendiente): La operación asíncrona aún no ha terminado.
Fulfilled (cumplida): La operación se completó exitosamente.
Rejected (rechazada): La operación falló.

Sintaxis básica de una Promise

const miPromesa = new Promise((resolve, reject) => {
let exito = true;

if (exito) {
resolve(“¡Operación exitosa!”);
} else {
reject(“Hubo un error.”);
}
});

// Consumir la Promise
miPromesa
.then(resultado => console.log(resultado)) // Si se resuelve
.catch(error => console.error(error)); // Si se rechaza

¿Qué son los Polyfills de Promises?

Un polyfill es un código que implementa una funcionalidad que no está disponible en algunos navegadores antiguos. Dado que las Promises se introdujeron en ES6 (2015), navegadores más antiguos no las soportan. Librerías como es6-promise o bluebird ofrecen polyfills para garantizar compatibilidad.
Cómo Responder a la Pregunta

Si te preguntan esto en una entrevista o evaluación, podrías responder de la siguiente manera, dependiendo de tu experiencia:

Básico:
"Tengo experiencia usando Promises para manejar operaciones asíncronas en JavaScript, como solicitudes HTTP con fetch. También estoy familiarizado con el uso de .then() y .catch() para manejar resoluciones y errores."

Intermedio:
"Además de usar Promises para manejar flujos asíncronos, sé cómo usar métodos como Promise.all y Promise.race para manejar múltiples Promises en paralelo. También entiendo cómo funcionan los polyfills y he usado librerías como es6-promise para compatibilidad en navegadores antiguos."

Avanzado:
"Tengo experiencia profunda con Promises y su manejo en aplicaciones complejas. He trabajado con polyfills como bluebird para mejorar el rendimiento y he migrado código basado en callbacks a un enfoque basado en Promises. También combino Promises con async/await para simplificar el manejo de operaciones asíncronas."

¿Te gustaría ejemplos más específicos o más detalles sobre algún concepto? 😊

j
ChatGPT puede cometer errores. Compru

34
Q

“¿Cuáles son las ventajas y desventajas de usar Promises en lugar de callbacks?”

A

Explicación
¿Qué son los Callbacks?

Un callback es una función que se pasa como argumento a otra función y se ejecuta después de que una operación asíncrona se complete.

Ejemplo básico con callbacks:

function fetchData(callback) {
setTimeout(() => {
callback(“Datos recibidos”);
}, 1000);
}

fetchData((data) => {
console.log(data); // Salida: “Datos recibidos”
});

¿Qué son las Promises?

Una Promise es una estructura más moderna para manejar operaciones asíncronas que resuelve o rechaza un valor en el futuro. Ofrecen una alternativa más limpia y escalable al manejo de callbacks.

Ejemplo básico con Promises:

function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(“Datos recibidos”);
}, 1000);
});
}

fetchData().then((data) => console.log(data)); // Salida: “Datos recibidos”

Ventajas de usar Promises en lugar de callbacks

Evita el "callback hell":
Los callbacks anidados pueden hacer que el código sea difícil de leer y mantener. Con Promises, el flujo es más claro y lineal.
Ejemplo de "callback hell":

getData((result) => {
processResult(result, (processed) => {
saveData(processed, (saved) => {
console.log(saved);
});
});
});

Con Promises, el mismo flujo es más limpio:

getData()
.then(processResult)
.then(saveData)
.then(console.log);

Manejo de errores centralizado:
Con Promises, puedes usar .catch() para manejar errores en una cadena completa, en lugar de manejar errores en cada callback.

getData()
  .then(processResult)
  .then(saveData)
  .catch((error) => console.error(error));

Compatibilidad con async/await:
Las Promises funcionan perfectamente con async/await, lo que permite escribir código asíncrono que parece síncrono, facilitando la lectura y el mantenimiento.

Composición más sencilla:
Métodos como Promise.all y Promise.race permiten manejar múltiples Promises en paralelo, algo que es complicado con callbacks.

Desventajas de usar Promises

Curva de aprendizaje:
Aunque más intuitivas que los callbacks anidados, las Promises pueden ser difíciles de entender para principiantes, especialmente con métodos avanzados como Promise.all o Promise.race.

Sobrecarga técnica en navegadores antiguos:
Algunos navegadores más antiguos no soportan Promises de manera nativa, lo que puede requerir el uso de polyfills como es6-promise.

Comportamiento silencioso en errores no manejados:
Si olvidas añadir un .catch() o manejar errores correctamente, las Promises pueden fallar silenciosamente, dificultando la depuración.

Mayor complejidad inicial:
Para operaciones muy simples, el uso de Promises puede parecer más complejo que un callback directo.

Resumen

Ventajas: Promises ofrecen un flujo más limpio, manejo centralizado de errores, y compatibilidad con async/await. Además, son ideales para operaciones asíncronas complejas o múltiples.
Desventajas: Requieren más conocimiento para usarlas correctamente y pueden complicar tareas muy simples en comparación con callbacks.
35
Q

What are some of the advantages/disadvantages of writing JavaScript code in a language that compiles to JavaScript?

A

Ventajas y desventajas de escribir código JavaScript en un lenguaje que se compila a JavaScript:

Ventajas:
1. Sintaxis más limpia o poderosa: Algunos lenguajes que compilan a JavaScript, como TypeScript o CoffeeScript, ofrecen una sintaxis más limpia o características de tipado que ayudan a evitar errores comunes en JavaScript. Esto puede mejorar la productividad y reducir errores.

  1. Mejor mantenimiento del código: Con lenguajes como TypeScript, puedes definir tipos y estructuras que facilitan la lectura y el mantenimiento del código, ya que es más claro qué valores se esperan y se identifican problemas en tiempo de compilación.
  2. Compatibilidad con navegadores antiguos: Los compiladores suelen generar JavaScript compatible con versiones antiguas de navegadores, lo cual es útil si necesitas que tu código funcione en una amplia variedad de entornos.
  3. Ecosistema más amplio: Al usar un lenguaje que compila a JavaScript, puedes beneficiarte de herramientas, extensiones y librerías adicionales que ayudan a crear aplicaciones más complejas y modulares.

Desventajas:
1. Dependencia en el proceso de compilación: Trabajar en un lenguaje que necesita compilarse antes de ser ejecutado puede hacer el desarrollo más lento y agregar una capa adicional de complejidad en el flujo de trabajo.

  1. Más difícil de depurar: Aunque las herramientas han mejorado mucho, a veces es más complicado rastrear errores, ya que el código compilado no siempre corresponde uno a uno con el código original.
  2. Tamaño del código generado: Algunas compilaciones pueden generar archivos JavaScript más grandes, lo que puede afectar el tiempo de carga y la eficiencia en dispositivos con recursos limitados.
  3. Curva de aprendizaje: Aprender un lenguaje adicional puede requerir tiempo y esfuerzo, especialmente si tienes que dominar las particularidades del compilador o el sistema de tipos del lenguaje nuevo.

Ventajas:

  • Soluciona algunos de los problemas persistentes en JavaScript y desalienta los anti-patrones de JavaScript.
  • Permite escribir un código más corto al proporcionar algunas facilidades de sintaxis (syntactic sugar) adicionales a JavaScript, que creo que faltan en ES5, aunque ES2015 es excelente.
  • Los tipos estáticos son muy útiles (en el caso de TypeScript) para proyectos grandes que necesitan mantenerse en el tiempo.

Desventajas:

  • Requiere un proceso de construcción/compilación, ya que los navegadores solo ejecutan JavaScript y tu código necesitará ser compilado a JavaScript antes de ser servido a los navegadores.
  • Depurar puede ser complicado si los mapas de origen no se corresponden bien con el código fuente precompilado.
  • La mayoría de los desarrolladores no están familiarizados con estos lenguajes y necesitarán aprenderlo, lo que implica un costo inicial para tu equipo si lo utilizas en tus proyectos.
  • Comunidad más pequeña (dependiendo del lenguaje), lo que significa que los recursos, tutoriales, librerías y herramientas pueden ser más difíciles de encontrar.
  • El soporte para IDE o editores podría ser limitado.
  • Estos lenguajes siempre estarán detrás del estándar más reciente de JavaScript.
  • Los desarrolladores deben ser conscientes de a qué se compila su código, ya que eso es lo que realmente se ejecutará y lo que importa al final.

Prácticamente, ES2015 ha mejorado considerablemente JavaScript y lo ha hecho mucho más agradable de escribir. Realmente no veo la necesidad de CoffeeScript en estos días.

36
Q

What tools and techniques do you use for debugging JavaScript code?

A

¿Qué herramientas y técnicas utilizas para depurar código JavaScript?

Herramientas comunes:

  1. Consola del navegador:
    • La mayoría de los navegadores modernos (como Chrome, Firefox, y Edge) tienen una consola de desarrollador que permite ejecutar comandos, inspeccionar variables, y ver errores en tiempo real.
    • Útil para verificar el estado de variables, imprimir mensajes (console.log()), y rastrear errores rápidamente.
  2. Depurador integrado:
    • Herramientas como las DevTools de Chrome permiten configurar puntos de interrupción (breakpoints) para pausar la ejecución del código y analizarlo paso a paso.
    • Ayuda a identificar el flujo del programa y localizar problemas específicos.
  3. Mapas de origen (Source Maps):
    • Si estás utilizando un lenguaje que compila a JavaScript (como TypeScript), los mapas de origen permiten vincular el código compilado con el original para facilitar la depuración.
  4. Extensiones y herramientas adicionales:
    • Extensiones como React Developer Tools o Vue Devtools permiten depurar aplicaciones específicas creadas con estos frameworks.
    • Linters como ESLint pueden detectar errores de sintaxis y patrones problemáticos antes de ejecutar el código.
  5. Entornos de desarrollo integrados (IDEs):
    • Editores como Visual Studio Code tienen depuradores integrados que se pueden usar junto con Node.js o navegadores.

Técnicas útiles:

  1. Uso de console.log():
    • Es una técnica básica pero efectiva para verificar valores y estados en diferentes puntos del código.
    • Ejemplo: console.log('Valor de x:', x);
  2. Configuración de puntos de interrupción:
    • Permite pausar la ejecución en líneas específicas del código para observar el estado de las variables y el flujo del programa.
  3. Verificación de errores en red:
    • Inspecciona las solicitudes HTTP en las DevTools para confirmar que los datos se envían y reciben correctamente.
    • Útil para depurar problemas relacionados con APIs o recursos externos.
  4. Modo “Strict”:
    • Usar "use strict"; al inicio del archivo o función ayuda a identificar errores comunes como variables no declaradas o asignaciones no válidas.
  5. Pruebas unitarias:
    • Herramientas como Jest o Mocha ayudan a probar partes del código de forma aislada para asegurarse de que cada componente funcione correctamente.
  6. Inspección de excepciones:
    • Manejar errores explícitamente usando try...catch y registrar los mensajes de error para analizar problemas inesperados.

Resumen:
Depurar JavaScript requiere una combinación de herramientas prácticas, como las DevTools del navegador, y técnicas como el uso de puntos de interrupción y console.log(). Además, frameworks y linters pueden ayudar a detectar errores antes de que el código se ejecute. ¡La clave es usar las herramientas adecuadas según la naturaleza del problema!

37
Q

¿Qué construcciones de lenguaje utilizas para iterar sobre las propiedades de un objeto y los elementos de un array?

A

¿Qué construcciones de lenguaje utilizas para iterar sobre las propiedades de un objeto y los elementos de un array?

Para iterar sobre propiedades de un objeto:

  1. for...in:
    • Recorre todas las propiedades enumerables de un objeto.
    • Ejemplo:
      javascript
      const objeto = { a: 1, b: 2, c: 3 };
      for (let clave in objeto) {
        console.log(clave, objeto[clave]);
      }
    • Nota: Esto también incluye propiedades heredadas, por lo que es útil usar hasOwnProperty si deseas solo las propiedades propias.
  2. Object.keys() con forEach:
    • Obtiene un array de las claves del objeto, luego puedes usar forEach para iterar sobre ellas.
    • Ejemplo:
      javascript
      Object.keys(objeto).forEach(clave => {
        console.log(clave, objeto[clave]);
      });
  3. Object.entries() con for...of:
    • Convierte el objeto en un array de pares [clave, valor], lo que facilita el recorrido.
    • Ejemplo:
      javascript
      for (let [clave, valor] of Object.entries(objeto)) {
        console.log(clave, valor);
      }

Para iterar sobre elementos de un array:

  1. for clásico:
    • Método tradicional para iterar utilizando un índice.
    • Ejemplo:
      javascript
      const array = [1, 2, 3];
      for (let i = 0; i < array.length; i++) {
        console.log(array[i]);
      }
  2. for...of:
    • Recorre directamente los elementos del array, sin necesidad de índices.
    • Ejemplo:
      javascript
      for (let elemento of array) {
        console.log(elemento);
      }
  3. Métodos de orden superior (forEach, map, filter, reduce):
    • Permiten iterar o transformar arrays de forma más declarativa.
    • Ejemplo con forEach:
      javascript
      array.forEach(elemento => {
        console.log(elemento);
      });
    • map se usa para crear un nuevo array transformando los elementos:
      javascript
      const duplicado = array.map(elemento => elemento * 2);
  4. for...in (evitar en arrays):
    • Aunque funciona, for...in no es ideal para arrays porque recorre también las propiedades enumerables y heredadas, lo cual no es siempre deseado para arrays.

Resumen:
Para objetos, uso for...in, Object.keys() con forEach, o Object.entries() con for...of para obtener un control preciso de las propiedades. Para arrays, prefiero for...of o métodos como forEach y map, ya que son más legibles y funcionales para trabajar con listas de elementos.

38
Q

Explain the difference between mutable and immutable objects

A

La inmutabilidad es un principio fundamental en la programación funcional, y también ofrece muchas ventajas en la programación orientada a objetos.

Un objeto mutable es aquel cuyo estado puede modificarse después de ser creado.
Un objeto inmutable es aquel cuyo estado no puede modificarse después de ser creado.

Ejemplo de un objeto inmutable en JavaScript:

En JavaScript, algunos tipos incorporados (como números y cadenas) son inmutables, pero los objetos personalizados suelen ser mutables.
Ejemplos de objetos inmutables incorporados:
- Math: Sus propiedades y métodos no se pueden modificar.
- Date: Aunque su estado interno puede cambiar (es mutable), el objeto original permanece estructuralmente igual.

Formas de agregar/simular inmutabilidad en objetos en JavaScript:

  1. Propiedades constantes de objetos:
    Combinando writable: false y configurable: false, se puede crear una constante como propiedad de un objeto.
    javascript
    let myObject = {};
    Object.defineProperty(myObject, 'number', {
      value: 42,
      writable: false,
      configurable: false,
    });
    console.log(myObject.number); // 42
    myObject.number = 43;
    console.log(myObject.number); // 42
  2. Prevenir extensiones (Object.preventExtensions):
    Esto evita que se añadan nuevas propiedades al objeto, pero las propiedades existentes permanecen intactas.
    ```javascript
    var myObject = { a: 2 };
    Object.preventExtensions(myObject);myObject.b = 3;
    console.log(myObject.b); // undefined
    ```
  3. Sellar (Object.seal):
    Sella un objeto al evitar que se le añadan o eliminen propiedades y marca las existentes como no configurables. Sin embargo, las propiedades pueden seguir siendo modificables.
    javascript
    var myObject = { a: 2 };
    Object.seal(myObject);
    myObject.a = 3; // Funciona
    delete myObject.a; // No funciona
    console.log(myObject.a); // 3
  4. Congelar (Object.freeze):
    Congela un objeto, evitando modificaciones, eliminaciones o reconfiguración de propiedades. Esta es la mayor forma de inmutabilidad disponible en JavaScript.
    javascript
    var immutable = Object.freeze({ a: 1 });
    immutable.a = 2; // No funciona
    console.log(immutable.a); // 1
    Nota: Object.freeze no afecta a objetos anidados.

Ventajas de la inmutabilidad:

  1. Detección más fácil de cambios:
    La igualdad de objetos puede determinarse de manera más sencilla y eficiente mediante igualdad referencial, útil en bibliotecas como React y Redux.
  2. Menor complejidad:
    Los programas son más fáciles de entender porque no necesitas preocuparte por cómo evoluciona un objeto con el tiempo.
  3. Sin necesidad de copias defensivas:
    Al pasar o devolver objetos inmutables, no hay riesgo de que sean modificados inesperadamente.
  4. Compartición sencilla mediante referencias:
    Una copia de un objeto es igual de válida que otra, lo que permite reutilización y almacenamiento en caché.
  5. Seguro para hilos:
    Los objetos inmutables son seguros para usar en entornos multihilo porque no hay riesgo de modificaciones concurrentes.
  6. Eficiencia con librerías como ImmutableJS:
    Las modificaciones se realizan mediante structural sharing, lo que reduce el consumo de memoria.

Desventajas de la inmutabilidad:

  1. Implementaciones ingenuas pueden ser ineficientes:
    Crear nuevos objetos cada vez puede resultar en un rendimiento muy pobre. Usar librerías optimizadas es esencial para mitigar este problema.
  2. Impacto en el rendimiento:
    La asignación y liberación de pequeños objetos repetidamente puede afectar la memoria y el rendimiento del programa.
  3. Estructuras de datos cíclicas son difíciles de construir:
    Por ejemplo, si dos objetos inmutables necesitan apuntarse entre sí, es complicado establecer esa relación sin romper la inmutabilidad.

Resumen:
La inmutabilidad aporta claridad, seguridad y facilidad de mantenimiento en el desarrollo de software, pero debe usarse con cuidado debido a su impacto potencial en el rendimiento y su complejidad al trabajar con estructuras avanzadas.

How can you achieve immutability in your own code?

One way to achieve immutability is to use libraries like immutable.js, mori or immer.

The alternative is to use const declarations combined with the techniques mentioned above for creation. For “mutating” objects, use the spread operator, Object.assign, Array.concat(), etc., to create new objects instead of mutate the original object.

Examples:

// Array Example
const arr = [1, 2, 3];
const newArr = […arr, 4]; // [1, 2, 3, 4]

// Object Example
const human = Object.freeze({ race: ‘human’ });
const john = { …human, name: ‘John’ }; // {race: “human”, name: “John”}
const alienJohn = { …john, race: ‘alien’ }; // {race: “alien”, name: “John”}

39
Q

Explica la diferencia entre funciones sincrónicas y asincrónicas

A

Explica la diferencia entre funciones sincrónicas y asincrónicas:

Funciones sincrónicas:

  1. Definición:
    • Son funciones que se ejecutan de forma secuencial, bloqueando el flujo del programa hasta que completen su tarea.
  2. Características:
    • Cada línea de código se ejecuta una después de otra.
    • El programa espera a que la tarea actual finalice antes de proceder a la siguiente.
    • Puede causar bloqueos si una operación toma mucho tiempo (por ejemplo, lectura de un archivo grande o cálculo intensivo).
  3. Ejemplo:
    ```javascript
    function sincrono() {
    console.log(“Inicio”);
    console.log(“Tarea sincrónica completada”);
    console.log(“Fin”);
    }sincrono();
    // Salida:
    // Inicio
    // Tarea sincrónica completada
    // Fin
    ```

Funciones asincrónicas:

  1. Definición:
    • Son funciones que permiten realizar tareas sin bloquear el flujo del programa, devolviendo el control inmediatamente.
  2. Características:
    • Pueden ejecutar tareas en segundo plano mientras el resto del código continúa ejecutándose.
    • Usan promesas, callbacks o la sintaxis async/await para manejar operaciones que toman tiempo, como solicitudes a servidores o temporizadores.
    • Ideales para operaciones como la lectura de datos remotos o la escritura en bases de datos.
  3. Ejemplo:
    ```javascript
    async function asincrono() {
    console.log(“Inicio”);
    await new Promise(resolve => setTimeout(resolve, 2000)); // Espera 2 segundos
    console.log(“Tarea asincrónica completada”);
    console.log(“Fin”);
    }asincrono();
    // Salida:
    // Inicio
    // (Espera 2 segundos)
    // Tarea asincrónica completada
    // Fin
    ```

Diferencias clave:

Resumen:
Las funciones sincrónicas son directas pero pueden bloquear el flujo del programa en tareas largas. Las funciones asincrónicas, por otro lado, permiten que el programa continúe ejecutándose mientras esperan que las tareas completen, lo que es útil para mejorar la eficiencia y la experiencia del usuario en aplicaciones modernas.

Sincrónico | Asincrónico |
|—————————————-|————————————-|
| Bloquea la ejecución del programa. | No bloquea la ejecución. |
| Se ejecuta de forma secuencial. | Permite ejecutar otras tareas mientras espera. |
| Menos complejo de implementar. | Puede requerir manejo adicional (promesas o async/await). |
| Ejemplo típico: operaciones simples. | Ejemplo típico: operaciones de red o entrada/salida. |

40
Q

Dame distintos ejemplos de funciones asincronas?

A

Aquí tienes varios ejemplos de funciones asincrónicas en JavaScript usando diferentes enfoques:

  1. Uso de setTimeout (Callback)
    El setTimeout es una función asincrónica que ejecuta un código después de un retraso determinado.

```javascript
console.log(“Inicio”);

setTimeout(() => {
console.log(“Este es un mensaje después de 2 segundos”);
}, 2000);

console.log(“Fin”);
// Salida:
// Inicio
// Fin
// (2 segundos de espera)
// Este es un mensaje después de 2 segundos
~~~

  1. Uso de Promesas
    Las promesas son una forma de manejar tareas asincrónicas que pueden completarse en el futuro.

```javascript
function tareaAsincrona() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(“Tarea completada después de 2 segundos”);
}, 2000);
});
}

tareaAsincrona().then((resultado) => {
console.log(resultado); // Salida: Tarea completada después de 2 segundos
});
~~~

  1. Uso de async y await
    Con la palabra clave async, podemos usar await para esperar que una promesa se resuelva antes de continuar con el flujo del código.

```javascript
async function ejemploAsync() {
console.log(“Inicio”);

const resultado = await new Promise((resolve) =>
setTimeout(() => resolve(“Tarea completada con async/await”), 2000)
);

console.log(resultado); // Salida: Tarea completada con async/await
console.log(“Fin”);
}

ejemploAsync();
// Salida:
// Inicio
// (2 segundos de espera)
// Tarea completada con async/await
// Fin
~~~

  1. Uso de fetch para hacer solicitudes HTTP
    La función fetch se usa para realizar solicitudes HTTP de manera asincrónica. La respuesta se maneja mediante promesas.

```javascript
async function obtenerDatos() {
const response = await fetch(‘https://jsonplaceholder.typicode.com/posts’);
const data = await response.json();
console.log(data);
}

obtenerDatos();
// Salida: Datos obtenidos de la API (puede ser un array de objetos)
~~~

  1. Uso de setInterval (Repetición asincrónica)
    setInterval ejecuta una función repetidamente con un intervalo de tiempo especificado.

```javascript
let contador = 0;

const intervalId = setInterval(() => {
console.log(Segundos transcurridos: ${contador});
contador++;

if (contador === 5) {
clearInterval(intervalId); // Detener el intervalo después de 5 segundos
}
}, 1000);
// Salida (aproximadamente cada segundo):
// Segundos transcurridos: 0
// Segundos transcurridos: 1
// Segundos transcurridos: 2
// Segundos transcurridos: 3
// Segundos transcurridos: 4
~~~

  1. Operaciones asincrónicas con Promise.all()
    Promise.all() permite ejecutar varias promesas en paralelo y esperar a que todas se resuelvan.

```javascript
async function operacionesEnParalelo() {
const promesa1 = new Promise((resolve) => setTimeout(() => resolve(“Tarea 1”), 1000));
const promesa2 = new Promise((resolve) => setTimeout(() => resolve(“Tarea 2”), 2000));
const promesa3 = new Promise((resolve) => setTimeout(() => resolve(“Tarea 3”), 1500));

const resultados = await Promise.all([promesa1, promesa2, promesa3]);
console.log(resultados); // Salida: [ ‘Tarea 1’, ‘Tarea 2’, ‘Tarea 3’ ]
}

operacionesEnParalelo();
~~~

Resumen:
- setTimeout y setInterval: Permiten ejecutar código con un retraso o repetidamente.
- Promesas: Usadas para manejar tareas asincrónicas que pueden completarse en el futuro.
- async/await: Una forma más limpia de manejar funciones asincrónicas usando promesas.
- fetch: Para realizar solicitudes HTTP de manera asincrónica.

Estos ejemplos cubren diversas situaciones de uso común para manejar tareas asincrónicas en JavaScript, mejorando el rendimiento y evitando bloqueos en el programa.

41
Q

¿Qué es el Event Loop? ¿Cuál es la diferencia entre la Call Stack y la Task Queue?

A

¿Qué es el Event Loop? ¿Cuál es la diferencia entre la Call Stack y la Task Queue?

Event Loop (Bucle de eventos):

El event loop es un mecanismo que permite que JavaScript maneje la ejecución de código de manera asincrónica, incluso cuando el lenguaje es de un solo hilo (single-threaded). El propósito principal del event loop es gestionar y coordinar la ejecución de tareas en un hilo único, permitiendo que el código asincrónico (como las promesas o los eventos) no bloquee el flujo principal del programa.

En términos simples, el event loop observa dos estructuras principales:
1. Call Stack (Pila de ejecución): Donde se ejecuta el código de manera secuencial.
2. Task Queue (Cola de tareas): Donde se colocan las funciones y eventos que deben ejecutarse después de que se vacíe la call stack.

El event loop asegura que las funciones asincrónicas, como los setTimeout, fetch, y otros eventos, no bloqueen la ejecución del programa. El loop revisa continuamente la call stack, y cuando está vacía, mueve las funciones de la task queue a la call stack para que se ejecuten.

Call Stack (Pila de ejecución):

  1. Definición:
    La call stack es una estructura de datos que sigue el principio LIFO (Last In, First Out) y maneja la ejecución de funciones. Cada vez que se invoca una función, esta se coloca en la call stack, y cuando esa función termina su ejecución, se elimina de la pila.
  2. Funcionamiento:
    • Cuando el código se ejecuta de manera sincrónica, las funciones se apilan una sobre otra en la call stack.
    • Cuando se completa la ejecución de una función, se desapila y se regresa al punto anterior.
  3. Ejemplo:
    ```javascript
    function funcion1() {
    console.log(“Inicio de funcion1”);
    funcion2(); // Llamada a funcion2
    console.log(“Fin de funcion1”);
    }function funcion2() {
    console.log(“Dentro de funcion2”);
    }funcion1();
    // Salida:
    // Inicio de funcion1
    // Dentro de funcion2
    // Fin de funcion1
    ```

Task Queue (Cola de tareas):

  1. Definición:
    La task queue es una lista de tareas (o eventos) que esperan para ser ejecutadas, pero solo se ejecutan cuando la call stack está vacía. Estas tareas son generalmente el resultado de operaciones asincrónicas, como callbacks de setTimeout, fetch, o eventos de usuario.
  2. Funcionamiento:
    • Cuando una función asincrónica se completa, su callback se coloca en la task queue.
    • El event loop mueve estas tareas a la call stack cuando está vacía.
  3. Ejemplo:
    ```javascript
    console.log(“Inicio”);setTimeout(() => {
    console.log(“Tarea asincrónica completada”);
    }, 0);console.log(“Fin”);
    // Salida:
    // Inicio
    // Fin
    // Tarea asincrónica completada
    ```Aunque el setTimeout tiene un tiempo de espera de 0, la tarea asincrónica se coloca en la task queue y solo se ejecuta después de que la call stack esté vacía.

Diferencia entre Call Stack y Task Queue:

Resumen:

  • Call Stack (Pila de ejecución): Se encarga de ejecutar las funciones de manera secuencial y sincrónica.
  • Task Queue (Cola de tareas): Almacena las tareas asincrónicas que se ejecutan una vez que la call stack está vacía.
  • Event Loop: Un mecanismo que permite ejecutar funciones asincrónicas de manera eficiente, trasladando las tareas de la task queue a la call stack cuando esta última está vacía.

Call Stack | Task Queue |
|——————————————–|———————————————|
| Es donde se ejecutan las funciones sincrónicas. | Es donde se colocan las tareas asincrónicas (como callbacks, promesas, eventos). |
| La ejecución de funciones es secuencial y bloqueante. | Las tareas se ejecutan solo cuando la call stack está vacía. |
| Las funciones se apilan y desapilan conforme se invocan y completan. | Las tareas son procesadas en el orden en que se añaden (FIFO: First In, First Out). |

42
Q

Diferencias en el uso de foo entre function foo() {} y var foo = function() {}

A

Diferencias en el uso de foo entre function foo() {} y var foo = function() {}

En JavaScript, hay dos maneras comunes de declarar funciones: usando declaraciones de funciones y expresiones de función. Las diferencias entre function foo() {} y var foo = function() {} se deben a la hoisting, el alcance de la variable y la asignación de la función.

  1. Hoisting (Elevación):
    • Declaración de Función (function foo() {}):
      • Las declaraciones de función son hoisted (elevadas), lo que significa que el motor de JavaScript las mueve al inicio del contexto de ejecución (función o global), antes de que se ejecute cualquier código. Por lo tanto, la función puede ser llamada antes de su declaración en el código.
      • Ejemplo:
        ```javascript
        foo(); // Funciona porque la función está hoisted.function foo() {
        console.log(“Hola desde foo”);
        }
        ```
    • Expresión de Función (var foo = function() {}):
      • Las expresiones de función no son completamente hoisted. Solo se eleva la declaración de la variable, pero la asignación de la función se realiza en tiempo de ejecución. Esto significa que no se puede llamar a la función antes de su definición.
      • Ejemplo:
        ```javascript
        foo(); // Error, porque foo es undefined al principio.var foo = function() {
        console.log(“Hola desde foo”);
        };
        ```
    • Diferencia clave: Con la declaración de función, puedes llamar a la función antes de su definición, mientras que con la expresión de función, debes definir la función antes de invocarla.
  1. Alcance (Scope):
    • Declaración de Función (function foo() {}):
      • La función se asocia directamente al nombre y está disponible en el alcance (scope) donde se declara (global, función, bloque). Si la defines en el ámbito global, foo será accesible globalmente. Si se define dentro de una función, solo será accesible dentro de esa función.
      • Ejemplo:
        ```javascript
        function foo() {
        console.log(“Hola”);
        }foo(); // Funciona sin problemas
        ```
    • Expresión de Función (var foo = function() {}):
      • La función es asignada a la variable foo, y por lo tanto, su alcance depende de esa variable. La función solo será accesible después de la asignación de la variable, es decir, después de que se ejecute la línea var foo = function() {}.
      • Ejemplo:
        ```javascript
        var foo = function() {
        console.log(“Hola”);
        };foo(); // Funciona después de la asignación.
        ```
  1. Reasignación y Funciones Anónimas:
    • Declaración de Función (function foo() {}):
      • La declaración de función no permite reasignar el nombre de la función. Una vez que defines foo, foo siempre será una función.
      • Ejemplo:
        ```javascript
        function foo() {
        console.log(“Hola”);
        }foo = 42; // Error, no puedes reasignar foo a otro tipo.
        ```
    • Expresión de Función (var foo = function() {}):
      • En las expresiones de función, como la función es asignada a una variable, puedes reasignar esa variable a otra cosa, incluso a otra función o un valor diferente.
      • Ejemplo:
        ```javascript
        var foo = function() {
        console.log(“Hola”);
        };foo = 42; // Funciona, foo ahora es un número.
        ```
    • Funciones Anónimas:
      • Las expresiones de función son más comunes cuando se utilizan funciones anónimas, es decir, funciones sin nombre, asignadas a una variable.
      • Ejemplo de función anónima:
        javascript
        var foo = function() {
            console.log("Soy una función anónima");
        };
  1. Dependencia de Asignación y Ejecución:
    • Declaración de Función (function foo() {}):
      • Las funciones declaradas están listadas y disponibles inmediatamente cuando el código comienza a ejecutarse (por la elevación o hoisting). No dependen de cuándo se asigna o se ejecuta el código.
    • Expresión de Función (var foo = function() {}):
      • La función solo está disponible después de la asignación. Esto significa que si tratas de acceder a la función antes de la línea var foo = function() {}, obtendrás un error.

Resumen de las diferencias:

¿Cuál usar?
- Declaración de función: Es útil cuando necesitas que la función esté disponible en todo su alcance desde el principio y no se necesite reasignar.
- Expresión de función: Es más flexible, especialmente cuando trabajas con funciones anónimas, callbacks o cuando quieres poder reasignar la función más tarde.

Característica | Declaración de Función (function foo() {}) | Expresión de Función (var foo = function() {}) |
|———————————–|—————————————————-|—————————————————–|
| Hoisting | La función es hoisted, disponible antes de la definición | La variable foo es hoisted, pero la función se asigna en tiempo de ejecución. |
| Alcance | Función disponible en el ámbito donde se declara | Función disponible solo después de la asignación. |
| Reasignación | No puede ser reasignada a otro valor | La variable foo puede ser reasignada a otros valores o funciones. |
| Nombre | La función tiene un nombre (foo) | La función puede ser anónima, y se asigna a la variable foo. |
| Uso común | Ideal para definir funciones globales o locales | Útil para funciones anónimas o cuando se asigna una función a una variable. |

43
Q

What are the differences between variables created using let, var or const?

A

Variables declared using the var keyword are scoped to the function in which they are created, or if created outside of any function, to the global object. let and const are block scoped, meaning they are only accessible within the nearest set of curly braces (function, if-else block, or for-loop).

function foo() {
// All variables are accessible within functions.
var bar = ‘bar’;
let baz = ‘baz’;
const qux = ‘qux’;

console.log(bar); // bar
console.log(baz); // baz
console.log(qux); // qux
}

console.log(bar); // ReferenceError: bar is not defined
console.log(baz); // ReferenceError: baz is not defined
console.log(qux); // ReferenceError: qux is not defined

if (true) {
var bar = ‘bar’;
let baz = ‘baz’;
const qux = ‘qux’;
}

// var declared variables are accessible anywhere in the function scope.
console.log(bar); // bar
// let and const defined variables are not accessible outside of the block they were defined in.
console.log(baz); // ReferenceError: baz is not defined
console.log(qux); // ReferenceError: qux is not defined

var allows variables to be hoisted, meaning they can be referenced in code before they are declared. let and const will not allow this, instead throwing an error.

console.log(foo); // undefined

var foo = ‘foo’;

console.log(baz); // ReferenceError: can’t access lexical declaration ‘baz’ before initialization

let baz = ‘baz’;

console.log(bar); // ReferenceError: can’t access lexical declaration ‘bar’ before initialization

const bar = ‘bar’;

Redeclaring a variable with var will not throw an error, but let and const will.

var foo = ‘foo’;
var foo = ‘bar’;
console.log(foo); // “bar”

let baz = ‘baz’;
let baz = ‘qux’; // Uncaught SyntaxError: Identifier ‘baz’ has already been declared

let and const differ in that let allows reassigning the variable’s value while const does not.

// This is fine.
let foo = ‘foo’;
foo = ‘bar’;

// This causes an exception.
const baz = ‘baz’;
baz = ‘qux’;

44
Q

¿Cuáles son las diferencias entre las clases de ES6 y los constructores de funciones de ES5?

A

Traducción:
¿Cuáles son las diferencias entre las clases de ES6 y los constructores de funciones de ES5?

Explicación:
En JavaScript, tanto las clases de ES6 como los constructores de funciones de ES5 se utilizan para crear objetos y gestionar la herencia, pero tienen diferencias clave en sintaxis y características:

1. Sintaxis:
- ES5 Function Constructors:
Utilizan funciones tradicionales para definir un “constructor”.

javascript
  function Person(name, age) {
    this.name = name;
    this.age = age;
  }
  Person.prototype.greet = function () {
    console.log(`Hi, I'm ${this.name}`);
  };
 
  • ES6 Classes:
    Introducen una sintaxis más clara y orientada a objetos.
    javascript
    class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
      greet() {
        console.log(`Hi, I'm ${this.name}`);
      }
    }

2. Herencia:
- ES5:
La herencia se logra mediante Object.create() y asignaciones manuales al prototipo.

javascript
  function Employee(name, age, job) {
    Person.call(this, name, age); // Llamar al constructor padre
    this.job = job;
  }
  Employee.prototype = Object.create(Person.prototype);
  Employee.prototype.constructor = Employee;
 
  • ES6:
    La herencia se simplifica con la palabra clave extends y super para llamar al constructor padre.
    javascript
    class Employee extends Person {
      constructor(name, age, job) {
        super(name, age); // Llamar al constructor padre
        this.job = job;
      }
    }

3. strict mode:
- ES5:
El modo estricto no está habilitado de forma predeterminada, pero puedes activarlo manualmente usando "use strict";.

  • ES6:
    Todas las clases de ES6 operan en modo estricto automáticamente, lo que ayuda a evitar errores comunes (por ejemplo, asignar valores a variables no declaradas).

4. Hoisting (Elevación):
- ES5:
Los constructores de funciones son “elevados”, lo que significa que puedes utilizarlos antes de declararlos, aunque esto puede causar confusión.

javascript
  const john = new Person('John', 30); // Funciona
  function Person(name, age) {
    this.name = name;
    this.age = age;
  }
 
  • ES6:
    Las clases no son elevadas. Debes declararlas antes de usarlas.
    javascript
    const john = new Person('John', 30); // Error: Cannot access 'Person' before initialization
    class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
    }

5. Métodos estáticos:
- ES5:
Los métodos estáticos se asignan manualmente al constructor.

javascript
  function Person(name, age) {
    this.name = name;
    this.age = age;
  }
  Person.sayHello = function () {
    console.log('Hello!');
  };
 
  • ES6:
    Los métodos estáticos se declaran con la palabra clave static dentro de la clase.
    javascript
    class Person {
      static sayHello() {
        console.log('Hello!');
      }
    }

6. Legibilidad y mantenimiento:
- ES5:
La estructura del código puede ser más difícil de leer y mantener debido a la manipulación manual de prototipos y herencia.

  • ES6:
    Ofrece una sintaxis más limpia y cercana a lenguajes orientados a objetos tradicionales.

Conclusión:
Aunque ambos enfoques pueden lograr resultados similares, las clases de ES6 ofrecen una sintaxis más clara y moderna, junto con características como herencia simplificada y métodos estáticos, haciéndolas preferibles para nuevos proyectos. Sin embargo, los constructores de funciones de ES5 aún son relevantes para compatibilidad con navegadores antiguos o cuando no se puede usar ES6.

45
Q

Can you offer a use case for the new arrow => function syntax? How does this new syntax differ from other functions?

A

Traducción:
¿Puedes ofrecer un caso de uso para la nueva sintaxis de funciones flecha =>? ¿En qué se diferencia esta nueva sintaxis de otras funciones?

Explicación:
Las funciones flecha (=>) introducidas en ES6 son una alternativa más compacta a las funciones tradicionales. Tienen diferencias clave que las hacen ideales en ciertos casos de uso.

1. Diferencias principales:

a) Contexto de this:
- Funciones tradicionales:
El valor de this depende de cómo se llama la función, lo que puede llevar a confusiones.

javascript
  function traditionalFunction() {
    console.log(this);
  }
  traditionalFunction(); // `this` es el objeto global (o `undefined` en strict mode)
 
  • Funciones flecha:
    No tienen su propio this. En su lugar, heredan el this del contexto donde se definen. Esto las hace ideales para evitar el “binding” manual de this.
    ```javascript
    const obj = {
    value: 10,
    arrowFunction: () => console.log(this.value),
    traditionalFunction: function () {
    console.log(this.value);
    },
    };obj.arrowFunction(); // undefined (hereda this del contexto global)
    obj.traditionalFunction(); // 10
    ```

b) Sintaxis más concisa:
- Funciones tradicionales:
Requieren más palabras clave.

javascript
  const double = function (x) {
    return x * 2;
  };
 
  • Funciones flecha:
    Son más compactas, especialmente para funciones simples.
    javascript
    const double = (x) => x * 2;

c) Uso de arguments:
- Funciones tradicionales:
Tienen acceso a un objeto pseudo-array llamado arguments, que contiene todos los parámetros pasados.

javascript
  function traditionalFunction() {
    console.log(arguments);
  }
  traditionalFunction(1, 2, 3); // [1, 2, 3]
 
  • Funciones flecha:
    No tienen su propio arguments. Para acceder a los parámetros, se debe usar el operador rest (...).
    javascript
    const arrowFunction = (...args) => console.log(args);
    arrowFunction(1, 2, 3); // [1, 2, 3]

2. Caso de uso práctico:

a) Callbacks, especialmente en funciones como map, filter, y reduce:
La sintaxis concisa de las funciones flecha las hace ideales para escribir funciones anónimas en operaciones de arrays.
```javascript
const numbers = [1, 2, 3];
const doubled = numbers.map((n) => n * 2); // [2, 4, 6]
~~~

b) Métodos como setTimeout o addEventListener:
La herencia de this elimina la necesidad de usar bind o variables adicionales.
```javascript
class Timer {
constructor() {
this.seconds = 0;
}
start() {
setInterval(() => {
this.seconds++;
console.log(this.seconds); // Correcto: this se refiere a la instancia del Timer
}, 1000);
}
}
~~~

c) Evitar problemas con this en clases:
```javascript
class Counter {
constructor() {
this.count = 0;
document.addEventListener(‘click’, () => {
this.count++;
console.log(this.count); // Correcto: this se refiere a la instancia de Counter
});
}
}
~~~

Conclusión:
Las funciones flecha son especialmente útiles en situaciones donde no necesitas un nuevo contexto de this o cuando buscas una sintaxis más breve para funciones simples. Sin embargo, no son adecuadas si necesitas arguments o un this dinámico. Por ello, su elección depende del contexto de uso.

46
Q

What advantage is there for using the arrow syntax for a method in a constructor?

A

Traducción:

La principal ventaja de usar una función flecha como método dentro de un constructor es que el valor de this se establece en el momento de la creación de la función y no puede cambiar después. Por lo tanto, cuando el constructor se utiliza para crear un nuevo objeto, this siempre hará referencia a ese objeto.

Por ejemplo, supongamos que tenemos un constructor Person que toma un nombre como argumento y tiene dos métodos para imprimir ese nombre en la consola, uno como una función regular y otro como una función flecha:

```javascript
const Person = function (firstName) {
this.firstName = firstName;
this.sayName1 = function () {
console.log(this.firstName);
};
this.sayName2 = () => {
console.log(this.firstName);
};
};

const john = new Person(‘John’);
const dave = new Person(‘Dave’);

john.sayName1(); // John
john.sayName2(); // John

// La función regular puede cambiar el valor de ‘this’, pero la función flecha no
john.sayName1.call(dave); // Dave (porque “this” ahora es el objeto dave)
john.sayName2.call(dave); // John

john.sayName1.apply(dave); // Dave (porque “this” ahora es el objeto dave)
john.sayName2.apply(dave); // John

john.sayName1.bind(dave)(); // Dave (porque “this” ahora es el objeto dave)
john.sayName2.bind(dave)(); // John

var sayNameFromWindow1 = john.sayName1;
sayNameFromWindow1(); // undefined (porque “this” ahora es el objeto global, window)

var sayNameFromWindow2 = john.sayName2;
sayNameFromWindow2(); // John
~~~

El punto clave aquí es que this puede cambiar en una función normal, pero el contexto siempre permanece igual para una función flecha. Por lo tanto, incluso si pasas tu función flecha a diferentes partes de tu aplicación, no tendrás que preocuparte por que el contexto cambie.

Esto puede ser particularmente útil en componentes de clase en React. Si defines un método de clase, como un controlador de clics, utilizando una función normal y luego pasas ese controlador de clics como prop a un componente hijo, tendrás que vincular manualmente this en el constructor del componente padre. En cambio, si utilizas una función flecha, no es necesario vincular this manualmente, ya que el método obtendrá automáticamente el valor de this desde su contexto léxico de encierro.

(Puedes consultar este artículo para una demostración y un ejemplo de código).

47
Q

Cual es la definicion de higher order functions?

A

Traducción:
¿Cuál es la definición de una función de orden superior?

Definición:
Una función de orden superior (higher-order function) es una función que:
1. Toma una o más funciones como argumentos, o
2. Devuelve otra función como resultado.

Esto significa que las funciones de orden superior trabajan con otras funciones, ya sea utilizándolas o generándolas.

Explicación:

Las funciones de orden superior son un concepto central en la programación funcional. Permiten tratar las funciones como valores, lo que da flexibilidad para escribir código más modular, reutilizable y limpio.

Ejemplo 1: Recibir funciones como argumentos
La función filter en JavaScript es un ejemplo clásico. Filtra elementos de un array basándose en una función pasada como argumento.

```javascript
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter((num) => num % 2 === 0); // [2, 4]
~~~
En este caso, filter es una función de orden superior porque recibe una función (el callback (num) => num % 2 === 0) como argumento.

Ejemplo 2: Devolver funciones
Una función puede devolver otra función para personalizar su comportamiento.

```javascript
function multiplier(factor) {
return (num) => num * factor;
}

const triple = multiplier(3);
console.log(triple(5)); // 15
~~~
Aquí, multiplier es una función de orden superior porque devuelve una nueva función que multiplica un número por un factor dado.

Ejemplo 3: Combinación de ambas características
Algunas funciones hacen ambas cosas: reciben funciones como argumentos y devuelven otras funciones.

```javascript
function compose(f, g) {
return (x) => f(g(x));
}

const add = (x) => x + 2;
const multiply = (x) => x * 3;

const combined = compose(add, multiply);
console.log(combined(5)); // (5 * 3) + 2 = 17
~~~

Conclusión:
Las funciones de orden superior permiten manejar funciones como datos, lo que es clave para la programación funcional. Son útiles en muchos contextos, como procesamiento de datos, personalización de comportamiento y composición de funciones.

DIRECTO DE LA WEB

Traducción:

Una función de orden superior es cualquier función que toma una o más funciones como argumentos, las cuales utiliza para operar sobre algún dato, y/o devuelve una función como resultado. Las funciones de orden superior están diseñadas para abstraer operaciones que se realizan repetidamente.

El ejemplo clásico de esto es map, que toma un array y una función como argumentos. Luego, map utiliza esa función para transformar cada elemento del array y devuelve un nuevo array con los datos transformados. Otros ejemplos populares en JavaScript son forEach, filter y reduce.

Una función de orden superior no necesita limitarse a la manipulación de arrays, ya que hay muchos casos en los que devolver una función desde otra función es útil. Un ejemplo de esto en JavaScript es Function.prototype.bind.

Ejemplo: Map
Supongamos que tenemos un array de nombres y queremos transformar cada string a mayúsculas.

Forma imperativa:
```javascript
const names = [‘irish’, ‘daisy’, ‘anna’];

const transformNamesToUppercase = function (names) {
const results = [];
for (let i = 0; i < names.length; i++) {
results.push(names[i].toUpperCase());
}
return results;
};
transformNamesToUppercase(names); // [‘IRISH’, ‘DAISY’, ‘ANNA’]
~~~
En este caso, utilizamos un bucle for para recorrer el array y transformarlo, pero el código es más largo y menos declarativo.

Con .map(transformerFn):
Usar .map() hace que el código sea más corto y declarativo:
```javascript
const transformNamesToUppercase = function (names) {
return names.map((name) => name.toUpperCase());
};
transformNamesToUppercase(names); // [‘IRISH’, ‘DAISY’, ‘ANNA’]
~~~

Aquí, map abstrae el proceso de iterar sobre el array y aplicar una transformación, haciendo que el código sea más limpio y fácil de entender.

48
Q

Can you give an example for destructuring an object or an array?

A

Destructuración es una expresión disponible en ES6 que permite una forma concisa y conveniente de extraer valores de objetos o arrays y colocarlos en variables individuales.

Destructuración de Arrays

```javascript
// Asignación de variables.
const foo = [‘one’, ‘two’, ‘three’];

const [one, two, three] = foo;
console.log(one); // “one”
console.log(two); // “two”
console.log(three); // “three”

// Intercambio de variables.
let a = 1;
let b = 3;

[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1
~~~

Destructuración de Objetos

```javascript
// Asignación de variables.
const o = { p: 42, q: true };
const { p, q } = o;

console.log(p); // 42
console.log(q); // true
~~~

La destructuración simplifica la extracción de valores de estructuras complejas, lo que mejora la legibilidad y reduce la cantidad de código necesario para realizar estas operaciones.

49
Q

Dame otro ejemplo de desestructuracion de objetos

A

Aquí tienes un ejemplo práctico de desestructuración de objetos en JavaScript:

Ejemplo: Obtener datos de un objeto de usuario

```javascript
const user = {
name: “Carlos”,
age: 30,
location: {
city: “Madrid”,
country: “España”,
},
};

// Desestructuración del objeto
const { name, age, location: { city, country } } = user;

console.log(name); // “Carlos”
console.log(age); // 30
console.log(city); // “Madrid”
console.log(country); // “España”
~~~

Explicación:
1. Extraemos las propiedades name y age directamente del objeto user.
2. Anidamos la desestructuración para acceder a city y country dentro de la propiedad location.
3. Esto nos permite obtener datos específicos sin necesidad de hacer múltiples accesos al objeto (por ejemplo, user.location.city).

Es una forma concisa y legible de acceder a las propiedades de un objeto.

50
Q

Como funcionan los template literals de ES6

A

Traducción:

Los literales de plantilla ayudan a simplificar la interpolación de cadenas, o para incluir variables en una cadena. Antes de ES2015, era común hacer algo así:

```javascript
var person = { name: ‘Tyler’, age: 28 };
console.log(
‘Hi, my name is ‘ + person.name + ‘ and I am ‘ + person.age + ‘ years old!’,
);
// ‘Hi, my name is Tyler and I am 28 years old!’
~~~

Con los literales de plantilla, ahora puedes crear el mismo resultado de esta manera:

```javascript
const person = { name: ‘Tyler’, age: 28 };
console.log(Hi, my name is ${person.name} and I am ${person.age} years old!);
// ‘Hi, my name is Tyler and I am 28 years old!’
~~~

Nota que utilizas comillas invertidas, no comillas simples o dobles, para indicar que estás usando un literal de plantilla y puedes insertar expresiones dentro de los marcadores ${}.

Un segundo caso de uso útil es la creación de cadenas multilínea. Antes de ES2015, podías crear una cadena multilínea de la siguiente manera:

```javascript
console.log(‘This is line one.\nThis is line two.’);
// This is line one.
// This is line two.
~~~

O si querías dividirlo en múltiples líneas en tu código para no tener que desplazarte hacia la derecha en tu editor de texto para leer una cadena larga, también podrías escribirlo así:

```javascript
console.log(‘This is line one.\n’ + ‘This is line two.’);
// This is line one.
// This is line two.
~~~

Los literales de plantilla, sin embargo, conservan el espacio que agregas a ellos. Por ejemplo, para crear la misma salida de múltiples líneas que creamos anteriormente, puedes simplemente hacer:

```javascript
console.log(This is line one. This is line two.);
// This is line one.
// This is line two.
~~~

Otro caso de uso de los literales de plantilla sería usarlos como sustituto de bibliotecas de plantillas para interpolaciones de variables simples:

```javascript
const person = { name: ‘Tyler’, age: 28 };
document.body.innerHTML = `

<div>
<p>Name: ${person.name}</p>
<p>Age: ${person.age}</p>
</div>

`;
~~~

Nota que tu código puede ser susceptible a XSS utilizando .innerHTML. ¡Sanitiza tus datos antes de mostrarlos si provienen de un usuario!

Explicación:

Los literales de plantilla permiten trabajar con cadenas de texto de manera más flexible y legible. Son especialmente útiles cuando se necesita insertar variables o expresiones dentro de un texto sin necesidad de concatenar strings y usar caracteres de escape como \n para saltos de línea.

Este enfoque facilita la escritura de código más limpio y facilita la creación de plantillas dinámicas, como en el ejemplo de interpolación de datos para mostrar información sobre un usuario en el DOM. Además, al usar literales de plantilla, se pueden evitar problemas de seguridad como las inyecciones de código (XSS), ya que los datos insertados se tratan como texto y no como código ejecutable.

51
Q

Can you give an example of a curry function and why this syntax offers an advantage?

A

Traducción:
¿Puedes darme un ejemplo de una función curry y por qué esta sintaxis ofrece una ventaja?

Explicación sobre Curry y sus Ventajas:

El currying es un concepto funcional en el que una función toma múltiples argumentos, pero en lugar de recibir todos esos argumentos de una vez, devuelve una nueva función que toma el siguiente argumento. Este proceso se repite hasta que todos los argumentos han sido proporcionados, y luego se realiza la operación.

El currying tiene ventajas, especialmente cuando se quiere crear funciones reutilizables o parciales, y permite una mayor flexibilidad.

Ejemplo de función curry:

```javascript
// Función curry para sumar
function add(a) {
return function (b) {
return a + b;
};
}

const addFive = add(5); // La función ‘addFive’ ahora es una función parcial que suma 5.
console.log(addFive(10)); // 15
console.log(addFive(20)); // 25

// Usando currying para sumar 3 números
const addTwoNumbers = add(2); // La función que agrega 2
const addThreeNumbers = addTwoNumbers(3); // Ahora agregar 3
console.log(addThreeNumbers(4)); // 9 (2 + 3 + 4)
~~~

Ventajas del currying:

  1. Reutilización de funciones:
    Al currificar una función, puedes reutilizar la misma función con diferentes combinaciones de argumentos. En el ejemplo, add(5) crea una nueva función que suma 5, la cual puedes usar tantas veces como quieras con diferentes valores.
  2. Funciones parciales:
    Puedes crear funciones parciales como addFive, que ya tiene el primer argumento (5) “preconfigurado”. Esto permite que se creen funciones más específicas sin tener que repetir todo el código.
  3. Mayor legibilidad y mantenimiento:
    Al tener funciones más pequeñas y especializadas, el código puede ser más fácil de entender y mantener. Las funciones pequeñas también pueden ser más fácilmente probadas.
  4. Composición de funciones:
    El currying también permite componer funciones de una manera más flexible. Dado que cada función devuelve una nueva función, puedes encadenar varias funciones curry para realizar operaciones más complejas.

Conclusión:

El currying es una técnica poderosa que permite crear funciones más modulares y reutilizables, especialmente cuando tienes un conjunto de operaciones que comparten algunos de los mismos parámetros. Esto mejora la flexibilidad del código y hace que sea más fácil manejar funciones complejas de forma escalable.

52
Q

Dame otro ejemplo de curryng

A

Traducción:

El currying es un patrón en el que una función con más de un parámetro se divide en varias funciones que, cuando se llaman en serie, acumulan todos los parámetros necesarios uno a la vez. Esta técnica puede ser útil para hacer que el código escrito en un estilo funcional sea más fácil de leer y componer. Es importante señalar que, para que una función sea curried, debe comenzar como una función única y luego descomponerse en una secuencia de funciones, cada una de las cuales acepta un parámetro.

```javascript
function curry(fn) {
if (fn.length === 0) {
return fn;
}

function _curried(depth, args) {
return function (newArgument) {
if (depth - 1 === 0) {
return fn(…args, newArgument);
}
return _curried(depth - 1, […args, newArgument]);
};
}

return _curried(fn.length, []);
}

function add(a, b) {
return a + b;
}

var curriedAdd = curry(add);
var addFive = curriedAdd(5);

var result = [0, 1, 2, 3, 4, 5].map(addFive); // [5, 6, 7, 8, 9, 10]
~~~

Explicación:

  1. Función curry:
    La función curry toma una función fn y la convierte en una versión curried, es decir, una versión que espera recibir los parámetros uno por uno. Si la longitud de los parámetros de la función (fn.length) es 0, significa que no necesita más parámetros, por lo que devuelve la función tal cual.
  2. Función _curried:
    Esta función interna se encarga de manejar los parámetros de forma progresiva. A medida que se llama, acumula los argumentos y, cuando todos los parámetros han sido proporcionados, invoca la función original fn con los argumentos completos.
  3. Ejemplo con add:
    La función add(a, b) toma dos parámetros. Al currificarla, obtenemos curriedAdd que acepta primero un argumento (como el 5 en addFive) y luego espera otro argumento para completar la operación.
  4. Uso con map:
    En el ejemplo, usamos el método map sobre el array [0, 1, 2, 3, 4, 5]. Al aplicar addFive, que es una función parcialmente aplicada, cada elemento del array se suma con 5, resultando en [5, 6, 7, 8, 9, 10].

Ventajas del Currying:

  • Composición de funciones: Permite crear funciones más simples y especializadas, como addFive, que puede ser reutilizada y combinada con otras funciones sin necesidad de repetir código.
  • Mayor flexibilidad: Al aplicar el currying, puedes crear funciones con menos parámetros y utilizarlas en distintos contextos, lo que hace que el código sea más modular y fácil de mantener.
53
Q

¿Cuáles son los beneficios de usar la sintaxis de propagación (spread syntax) y cómo se diferencia de la sintaxis de resto (rest syntax)?

A

Traducción:
¿Cuáles son los beneficios de usar la sintaxis de propagación (spread syntax) y cómo se diferencia de la sintaxis de resto (rest syntax)?

Explicación sobre Spread y Rest:

La sintaxis de propagación (spread) y la sintaxis de resto (rest) en JavaScript son dos conceptos relacionados, pero con propósitos diferentes. Ambas usan los tres puntos (...), pero se emplean en contextos distintos y tienen resultados diferentes.

1. Spread Syntax (Propagación):
La sintaxis de propagación permite descomponer una estructura iterable (como un array u objeto) en sus elementos individuales, de manera que puedas pasar esos elementos como valores separados a una función o crear una nueva estructura combinando varios elementos.

Beneficios del Spread Syntax:
- Copiar arrays u objetos fácilmente: Puedes crear una copia superficial de un array u objeto sin tener que recorrerlo manualmente.
- Combinar arrays u objetos de manera sencilla: Puedes combinar varias estructuras en una sola.
- Pasar elementos de un array como argumentos individuales: Esto es útil cuando se pasan varios valores a una función.

Ejemplo con arrays:
```javascript
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

// Copiar un array
const arrCopy = […arr1];
console.log(arrCopy); // [1, 2, 3]

// Combinar arrays
const combinedArr = […arr1, …arr2];
console.log(combinedArr); // [1, 2, 3, 4, 5, 6]
~~~

Ejemplo con objetos:
```javascript
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3 };

// Combinar objetos
const mergedObj = { …obj1, …obj2 };
console.log(mergedObj); // { a: 1, b: 2, c: 3 }
~~~

2. Rest Syntax (Resto):
La sintaxis de resto se usa para agrupar múltiples elementos en una sola variable. Esto es útil para obtener un número variable de argumentos en una función o cuando se desestructuran arrays u objetos y se quiere recoger los valores restantes.

Beneficios del Rest Syntax:
- Capturar un número variable de parámetros: Permite que una función reciba un número indefinido de argumentos como un array.
- Desestructuración más flexible: Puedes recoger las propiedades restantes de un objeto o los elementos restantes de un array.

Ejemplo en funciones:
```javascript
function sum(…numbers) {
return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3, 4)); // 10
~~~

Ejemplo con desestructuración:
```javascript
const [first, …rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [2, 3, 4, 5]
~~~

Diferencias clave entre Spread y Rest:

  1. Spread Syntax (Propagación):
    • Se usa cuando desempaquetas un array u objeto para pasarlo como elementos individuales.
    • Ejemplo: const newArray = [...arr]; (Copia un array).
    • Se utiliza al pasar elementos como argumentos o al combinar arrays u objetos.
  2. Rest Syntax (Resto):
    • Se usa cuando recoges múltiples elementos y los agrupas en una sola variable.
    • Ejemplo: const [first, ...rest] = arr; (Desestructura un array y agrupa el resto).
    • Se utiliza en la desestructuración de arrays u objetos o al recibir múltiples argumentos en una función.

Resumen:

  • Spread es útil cuando quieres expandir los elementos de una estructura iterable.
  • Rest es útil cuando quieres agrupar varios elementos en una sola variable o parámetro.

Ambos tienen sus beneficios, y dependiendo del contexto en el que los uses, pueden hacer tu código más limpio, eficiente y fácil de manejar.

54
Q

Dame otro ejemplo de spread syntax y rest syntax

A

Traducción:

La sintaxis de propagación (spread syntax) de ES6 es muy útil cuando se programa en un paradigma funcional, ya que permite crear fácilmente copias de arrays u objetos sin recurrir a métodos como Object.create, slice o funciones de bibliotecas. Esta característica del lenguaje se utiliza con frecuencia en proyectos de Redux y RxJS.

```javascript
function putDookieInAnyArray(arr) {
return […arr, ‘dookie’];
}

const result = putDookieInAnyArray([‘I’, ‘really’, “don’t”, ‘like’]); // [“I”, “really”, “don’t”, “like”, “dookie”]

const person = {
name: ‘Todd’,
age: 29,
};

const copyOfTodd = { …person };
~~~

La sintaxis de rest (rest syntax) de ES6 ofrece una forma abreviada de incluir un número arbitrario de argumentos que se pasarán a una función. Es como el inverso de la sintaxis de propagación, ya que toma datos y los agrupa en un array en lugar de desempaquetarlos, y funciona tanto en los argumentos de funciones como en las asignaciones de desestructuración de arrays y objetos.

```javascript
function addFiveToABunchOfNumbers(…numbers) {
return numbers.map((x) => x + 5);
}

const result = addFiveToABunchOfNumbers(4, 5, 6, 7, 8, 9, 10); // [9, 10, 11, 12, 13, 14, 15]

const [a, b, …rest] = [1, 2, 3, 4]; // a: 1, b: 2, rest: [3, 4]

const { e, f, …others } = {
e: 1,
f: 2,
g: 3,
h: 4,
}; // e: 1, f: 2, others: { g: 3, h: 4 }
~~~

Explicación:

  • Spread Syntax:
    La sintaxis de propagación (...) permite tomar los elementos de un array u objeto y expandirlos en nuevos contextos. En el ejemplo, con putDookieInAnyArray, estamos creando una nueva copia del array y agregando un nuevo elemento, 'dookie'. También, al copiar el objeto person, estamos creando una nueva referencia para copyOfTodd, manteniendo las propiedades del objeto original.
  • Rest Syntax:
    La sintaxis de resto (...) permite capturar un número arbitrario de elementos y agruparlos en un array. En la función addFiveToABunchOfNumbers, usamos el operador rest para capturar todos los argumentos pasados como un array y sumarle 5 a cada uno. De manera similar, en los ejemplos de desestructuración, ...rest captura el resto de los elementos de un array o las propiedades de un objeto que no se asignan a variables específicas.

Resumen:

  • Spread Syntax: Se usa para expandir arrays u objetos y crear nuevas estructuras con los elementos existentes.
  • Rest Syntax: Se usa para agrupar varios elementos en un array, permitiendo que una función o asignación reciba un número indefinido de elementos.
55
Q

Maneras de compartir archivos en javascript

A

Traducción:

¿Cómo puedes compartir código entre archivos en JavaScript?

Explicación:

En JavaScript, hay varias formas de compartir código entre archivos. La manera de hacerlo depende del entorno en el que estés trabajando (navegador o Node.js) y la versión de JavaScript que estés utilizando. A continuación, te explico las formas más comunes de compartir código entre archivos.

  1. Usando módulos de ES6 (ESModules):
    Desde ES6, JavaScript tiene soporte nativo para módulos, lo que permite importar y exportar funciones, objetos o variables entre diferentes archivos.

Cómo funciona:
- export se utiliza para exportar código (funciones, variables, objetos) de un archivo.
- import se utiliza para importar el código desde otro archivo.

Ejemplo:

Archivo 1: math.js
```javascript
// Exportar funciones
export function add(a, b) {
return a + b;
}

export function subtract(a, b) {
return a - b;
}
~~~

Archivo 2: app.js
```javascript
// Importar las funciones desde math.js
import { add, subtract } from ‘./math.js’;

console.log(add(2, 3)); // 5
console.log(subtract(5, 2)); // 3
~~~

Nota:
- En un navegador, necesitas usar el atributo type="module" en tu archivo HTML para que los módulos funcionen correctamente:

html
  <script type="module" src="app.js"></script>
 

- Los archivos deben ser accesibles mediante una ruta relativa o absoluta, y los módulos deben ser ejecutados desde un servidor (no solo abriendo el archivo HTML directamente en un navegador).
  1. Usando require y module.exports en Node.js:
    En el entorno de Node.js, puedes usar require para importar módulos y module.exports para exportar código de un archivo.

Cómo funciona:
- module.exports se utiliza para exportar código.
- require se utiliza para importar el código en otro archivo.

Ejemplo:

Archivo 1: math.js
```javascript
// Exportar funciones con module.exports
module.exports.add = function (a, b) {
return a + b;
};

module.exports.subtract = function (a, b) {
return a - b;
};
~~~

Archivo 2: app.js
```javascript
// Importar las funciones desde math.js
const math = require(‘./math’);

console.log(math.add(2, 3)); // 5
console.log(math.subtract(5, 2)); // 3
~~~

  1. Usando la etiqueta <script> en HTML (solo para navegador):
    Antes de ES6, se solían usar múltiples archivos <script> para incluir código JavaScript desde diferentes archivos. Sin embargo, con esta opción, no tienes un mecanismo directo para compartir funciones u objetos entre archivos.

Ejemplo:

```html
<!-- Archivo HTML -->





~~~

Archivo 1: math.js
```javascript
function add(a, b) {
return a + b;
}

function subtract(a, b) {
return a - b;
}
~~~

Archivo 2: app.js
```javascript
console.log(add(2, 3)); // 5
console.log(subtract(5, 2)); // 3
~~~

Limitación:
No es tan eficiente como usar módulos porque todas las funciones y variables estarán en el scope global, lo que puede generar conflictos entre archivos.

Resumen:

  • ES6 Modules (import/export): Usado para importar y exportar funciones y variables de manera modular y eficiente en proyectos que soporten ES6, como en aplicaciones modernas de navegador y Node.js.
  • CommonJS (require/module.exports): Usado principalmente en Node.js para importar y exportar funciones y objetos entre archivos.
  • Global Scope con <script>: Utilizado en entornos de navegador antes de ES6, pero con menos control sobre los espacios de nombres y mayor propensión a conflictos.

La mejor opción depende de tu entorno y las herramientas que estés utilizando. En la mayoría de los casos modernos, se recomienda el uso de módulos ES6 por su claridad y soporte nativo en JavaScript.

56
Q

“¿Por qué querrías crear miembros estáticos en una clase?

A

Traducción:
“¿Por qué querrías crear miembros estáticos en una clase?”

Explicación:
En programación orientada a objetos, los miembros estáticos (también conocidos como static members) son variables o métodos que pertenecen a la clase en lugar de a instancias individuales de esa clase. Esto significa que se pueden acceder sin necesidad de crear un objeto de esa clase. Algunas razones por las que podrías querer usar miembros estáticos son:

  1. Compartir datos entre todas las instancias de la clase:
    Los miembros estáticos son comunes a todas las instancias de la clase. Si tienes información o un contador que debe ser compartido entre todas las instancias, puedes usar un miembro estático para asegurarte de que todas las instancias accedan al mismo valor.
  2. Acceso sin instanciar la clase:
    Si necesitas un método o variable que no depende del estado de una instancia específica, puedes hacerlo estático. Esto es útil para funciones de utilidad o para valores que no cambian entre instancias.
  3. Mantener un único valor global:
    En casos donde necesitas un valor constante o una referencia única (como un contador global o un gestor de configuración), los miembros estáticos permiten mantener ese valor accesible de manera centralizada.
  4. Memoria eficiente:
    Al usar miembros estáticos, solo se almacena una copia del miembro en lugar de tener una copia por cada instancia de la clase, lo cual puede ser más eficiente en términos de memoria si tienes muchas instancias.

Ejemplo en código (en C#):
```csharp
class Contador
{
public static int cuenta = 0; // Miembro estático

public static void IncrementarCuenta()
{
    cuenta++;
} }

Contador.IncrementarCuenta();
Console.WriteLine(Contador.cuenta); // Salida: 1
~~~
En este ejemplo, cuenta es un miembro estático que se puede acceder directamente a través de la clase sin necesidad de crear un objeto Contador.

Traducción:
Los miembros estáticos de una clase (propiedades/métodos) no están vinculados a una instancia específica de la clase y tienen el mismo valor sin importar cuál instancia se esté refiriendo a ellos. Las propiedades estáticas suelen ser variables de configuración y los métodos estáticos generalmente son funciones de utilidad puras que no dependen del estado de la instancia.