preguntas de la entrevista del día 05

1. La diferencia entre sincrónico y asincrónico

Síncrono y Asíncrono son conceptos utilizados para describir los modos de ejecución del programa.

Sincronización significa que el código se ejecuta en orden y cada línea de código se ejecuta antes de que se ejecute la siguiente línea de código. En modo síncrono, cuando se realiza una operación que requiere mucho tiempo, el programa se bloquea hasta que se completa la operación antes de continuar con el siguiente paso. Esto significa que mientras se realiza la operación que requiere mucho tiempo, el programa no puede realizar otras tareas.

Asincrónico significa que la ejecución del código no depende del orden y puede continuar realizando otras tareas mientras espera que se complete una operación. En el modo asíncrono, las operaciones que consumen mucho tiempo se delegan a otros subprocesos o procesos para su procesamiento sin bloquear la ejecución del programa principal. Una vez que se completa la operación que requiere mucho tiempo, el sistema notificará al programa y ejecutará la función de devolución de llamada o el controlador de eventos correspondiente.

La programación asincrónica puede mejorar efectivamente el rendimiento y la capacidad de respuesta de un programa. Es especialmente útil cuando se requiere una gran cantidad de operaciones de E/S o solicitudes de red. Puede evitar el bloqueo del programa y permitir que se procesen múltiples tareas al mismo tiempo.

La programación asincrónica se puede dividir en las siguientes formas:

  1. Función de devolución de llamada (devolución de llamada): una vez completada la operación asincrónica, la función de devolución de llamada se utiliza para procesar los resultados o realizar la siguiente operación. La función de devolución de llamada se pasa como parámetro a la función asincrónica y se llama cuando se completa la operación asincrónica. Este es el estilo de programación asincrónica más común en JavaScript.

  2. Promesa: Promise es un mecanismo introducido en ECMAScript 6 para manejar operaciones asincrónicas. Representa la finalización o falla final de una operación asincrónica y puede encadenar múltiples operaciones para manejar y organizar mejor el código asincrónico.

  3. async/await: async/await es azúcar sintáctico para programación asincrónica introducida en ECMAScript 2017. El operador de espera se puede utilizar dentro de una función declarada con la palabra clave async para esperar a que se complete una operación asincrónica, lo que hace que el código asincrónico se parezca más a un código sincrónico y mejora la legibilidad.

  4. Evento: maneja operaciones asincrónicas de forma controlada por eventos. Cuando se completa la operación asincrónica, se activa el evento correspondiente y el programa responde al evento de finalización de la operación registrando un controlador de eventos.

  5. Patrón de observador: al definir el observador y los objetos observados, el observador puede monitorear los cambios de estado de lo observado y manejarlo en consecuencia. Una vez que el observador completa la operación asincrónica, notifica al observador para su procesamiento.

Estos métodos son patrones y técnicas comunes para manejar operaciones asincrónicas, y cada método tiene sus escenarios y características aplicables. Elegir el método de programación asincrónico apropiado según las necesidades específicas y el entorno de programación puede mejorar la capacidad de mantenimiento y el rendimiento del código.

La ejecución de código asincrónico implica los conceptos de macrotareas (Macro Tasks) y microtareas (Micro Tasks).

Las tareas macro se refieren a unidades de tareas de mayor granularidad, que generalmente incluyen un fragmento completo de código, devoluciones de llamadas de eventos, temporizadores, etc. En JavaScript, las tareas macro comunes incluyen setTimeout, setInterval, operaciones de E/S, eventos DOM, etc.

Las microtareas son unidades de tareas relativamente pequeñas que se generan durante la ejecución de macrotareas y se ejecutan antes del final de las macrotareas. Las microtareas comunes incluyen devoluciones de llamadas de Promise, MutationObserver, etc.

Durante la ejecución del bucle de eventos (Event Loop), cuando se ejecuta una macrotarea, se verificará la cola de microtareas (es decir, todas las microtareas registradas) y las microtareas en la cola se ejecutarán en secuencia. Solo cuando la cola de microtareas esté vacía se ejecutará la siguiente macrotarea.

En resumen, el proceso de ejecución de código asincrónico se puede resumir en los siguientes pasos:

  1. Ejecute la macrotarea actual.
  2. Verifique y ejecute todas las microtareas en la cola de microtareas.
  3. Actualice el renderizado (si es necesario).
  4. Ejecute la siguiente tarea macro y repita los pasos anteriores.

Utilice los conceptos de macrotareas y microtareas para comprender y gestionar mejor el orden de ejecución del código asincrónico y evitar bloqueos o comportamientos no deseados.

Para resumir las diferencias:

  • Sincronización significa ejecutar código en orden y bloquear la ejecución del programa; asincrónica significa ejecutar código fuera de orden y no bloquear la ejecución del programa.
  • El siguiente paso se realiza después de que se completa la operación sincrónica, mientras que la operación asincrónica se puede realizar en segundo plano y se notifica al programa que la operación se completa a través de una función de devolución de llamada o un controlador de eventos.
  • El modo síncrono es adecuado para operaciones simples, mientras que el modo asíncrono es adecuado para situaciones en las que es necesario procesar operaciones que requieren mucho tiempo, como grandes E/S o solicitudes de red.

En general, sincrónico y asincrónico son dos modos de ejecución de código diferentes. Elegir el modo apropiado según las necesidades reales puede mejorar la eficiencia y la capacidad de respuesta del programa.

2. Hable sobre la diferencia entre funciones de flecha y funciones ordinarias.

Existen algunas diferencias en la sintaxis y la funcionalidad entre la función de flecha y la función normal.

  1. Sintaxis concisa: la sintaxis de las funciones de flecha es más concisa. Las funciones se pueden definir mediante el símbolo de flecha "=>", omitiendo la palabra clave de función y las llaves. Por ejemplo:

    • Funciones ordinarias:function add(a, b) { return a + b; }
    • Función de flecha:(a, b) => a + b
  2. Escenarios aplicables: las funciones de flecha son generalmente más adecuadas para funciones simples que contienen solo una expresión y devuelven su resultado, mientras que las funciones ordinarias son adecuadas para lógica de funciones complejas o escenarios que requieren un contexto específico (este enlace).

  3. Vinculación de this: en una función normal, el valor de this es dinámico y varía dependiendo de cómo se llama la función. La función de flecha no tiene su propio enlace this, capturará el valor this del contexto actual. Esto en una función de flecha siempre apunta al alcance en el que está definido. Esto es útil para evitar estos problemas de vinculación y escribir funciones de devolución de llamada más concisas.

  4. Objeto de argumentos: se puede acceder argumentsa todos los parámetros pasados ​​a la función a través del objeto en funciones ordinarias. La función de flecha no tiene su propio objeto de argumentos y puede usar parámetros de descanso para recibir parámetros de función.

  5. Constructor: las funciones ordinarias se pueden utilizar como constructores para crear nuevas instancias de objetos y tener objetos prototipo. La función de flecha no se puede utilizar como constructor porque no tiene su propio enlace this.

En resumen, las funciones de flecha son más concisas, adecuadas para funciones simples y funciones de devolución de llamada, y evitan estos problemas de vinculación. Las funciones ordinarias son adecuadas para situaciones y lógica de funciones complejas que requieren un contexto específico. Al elegir qué tipo de función usar, debe hacer un juicio basado en las necesidades específicas y la lógica del código.

3. Métodos JS de recorrido de objetos y matrices, y comparación de varios métodos

Las formas comunes de iterar sobre matrices y objetos en JavaScript incluyen el uso de bucles for, bucles for…in, bucles for…of y el método Object.keys().

  1. Utilice un bucle for para iterar a través de la matriz:
const arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
    
    
  console.log(arr[i]);
}
  1. Utilice un bucle for…in para recorrer las propiedades de un objeto:
const obj = {
    
     a: 1, b: 2, c: 3 };
for (let key in obj) {
    
    
  if (obj.hasOwnProperty(key)) {
    
    
    console.log(key, obj[key]);
  }
}

Nota: Debe utilizar hasOwnProperty()el método para determinar si el atributo es el atributo del objeto en sí para evitar atravesar los atributos en la cadena del prototipo.

  1. Utilice for…of para recorrer una matriz (ES6+):
const arr = [1, 2, 3];
for (let value of arr) {
    
    
  console.log(value);
}

El bucle for...of atraviesa directamente los valores de los elementos de la matriz, que es más conciso.

  1. Iterar sobre las claves de un objeto usando el método Object.keys() (ES5+):
const obj = {
    
     a: 1, b: 2, c: 3 };
Object.keys(obj).forEach(key => {
    
    
  console.log(key, obj[key]);
});

El método Object.keys() devuelve una matriz que consta de las claves del objeto, que luego se puede iterar utilizando el método forEach().

Comparar:

  • El bucle for es la forma de recorrido más tradicional y general, adecuado para atravesar matrices y objetos con claves numéricas.
  • El bucle for...in es adecuado para atravesar las propiedades de un objeto, pero es necesario prestar atención al impacto de la cadena prototipo.
  • El bucle for...of es una forma concisa e intuitiva de atravesar matrices y no admite el recorrido de objetos.
  • El método Object.keys() obtiene convenientemente las claves de un objeto y accede a ellas iterando sobre las claves.

Elija el método transversal apropiado de acuerdo con las necesidades reales. Generalmente, los bucles for y for...of son los métodos más utilizados para atravesar matrices, mientras que los bucles for...in y el método Object.keys() son adecuados para atravesar. objetos.

4. Cómo resolver problemas entre dominios

Para resolver problemas entre dominios, existen varios enfoques comunes que puede adoptar:

  1. Uso compartido de recursos entre dominios (CORS): establezca encabezados de respuesta en el servidor para permitir el acceso entre dominios desde fuentes específicas (nombres de dominio, protocolos, puertos). Es necesario configurar la información correcta del encabezado de respuesta en el lado del servidor, como agregar Access-Control-Allow-Originun campo y especificar las fuentes a las que se permite el acceso.

  2. Servidor proxy: al configurar un servidor en el mismo dominio que una capa intermediaria, reenvía las solicitudes de los clientes al servidor de destino para lograr el acceso entre dominios. La solicitud del cliente se envía primero al servidor proxy, y luego el servidor proxy envía la solicitud al servidor de destino y devuelve el resultado al cliente.

  3. JSONP (JSON con relleno): aprovechando <script>el hecho de que la etiqueta no tiene restricciones entre dominios, al crear dinámicamente un <script>elemento y colocar la URL de la solicitud entre dominios en srcel atributo, los datos devueltos por el servidor se empaquetarán en la función de devolución de llamada y devuelto. JSONP solo se puede utilizar para solicitudes GET y requiere que el servidor de destino admita el formato para devolver la función de devolución de llamada especificada.

  4. WebSocket: utilice el protocolo WebSocket para la comunicación entre dominios. WebSocket es un nuevo protocolo proporcionado por HTML5 que establece una conexión persistente entre el navegador y el servidor, ambas partes pueden transmitir datos a través de comunicación asincrónica.

  5. Proxy inverso: configure un proxy inverso en el lado del servidor para reenviar las solicitudes del cliente al servidor de destino y modifique el encabezado de respuesta antes de que la respuesta se devuelva al cliente para eliminar las restricciones entre dominios. Las herramientas de proxy inverso comunes incluyen Nginx, Apache, etc.

Debe elegir la solución adecuada según la situación específica y asegurarse de que la información relevante esté configurada correctamente para lograr el acceso entre dominios. Al mismo tiempo, se debe prestar atención a la seguridad y la legalidad para evitar el uso indebido o la filtración de datos sensibles.

5.La diferencia entre XML y JSON

XML (lenguaje de marcado extensible) y JSON (notación de objetos JavaScript) son formatos de intercambio de datos comúnmente utilizados, pero existen algunas diferencias en la sintaxis y el uso.

  1. Forma gramatical:

    • XML utiliza etiquetas personalizadas para describir la estructura de datos, incluidas etiquetas de inicio <tag>, etiquetas de cierre </tag>y etiquetas de cierre automático <tag/>.
    • JSON utiliza pares clave-valor para describir datos. Las claves están entre comillas dobles. Los valores pueden ser cadenas, números, valores booleanos, matrices, objetos, etc.
  2. legibilidad:

    • XML se diseñó originalmente como un formato de texto legible adecuado para la lectura y escritura humana.
    • JSON es más compacto y conciso que XML y más fácil de leer, pero es ligeramente más débil que XML.
  3. Soporte de tipo de datos:

    • XML no tiene tipos de datos integrados y todos los datos se presentan en forma de texto. Los datos deben analizarse y transformarse antes de poder utilizarlos en el programa.
    • JSON admite tipos de datos básicos (cadenas, números, booleanos, nulos) y puede representar matrices y objetos, mapeándose más directamente a estructuras de datos en la mayoría de los lenguajes de programación.
  4. Escalabilidad:

    • XML tiene la capacidad de personalizar etiquetas y puede ampliarse con nuevas etiquetas y reglas según sea necesario.
    • JSON es una estructura simple de par clave-valor sin mecanismo de extensión oficial. Si se requiere expansión, esto generalmente se logra mediante acuerdos y negociaciones.
  5. Escenarios de aplicación:

    • XML se utiliza ampliamente en muchos campos de aplicaciones tradicionales, como el intercambio electrónico de datos (EDI), archivos de configuración, análisis de documentos, etc.
    • Debido a sus características livianas y fáciles de analizar, JSON se usa ampliamente en el desarrollo web, especialmente en combinación con el lenguaje JavaScript para lograr la transmisión de datos y la interacción entre el front-end y el back-end.

En resumen, tanto XML como JSON tienen sus propios escenarios aplicables, y la elección de qué formato utilizar depende de las necesidades específicas, el entorno de programación y el estilo de colaboración en equipo.

6. Hable sobre sus puntos de vista sobre el paquete web.

Webpack es una potente herramienta de empaquetado de módulos, que se utiliza principalmente para la gestión modular y la construcción de aplicaciones JavaScript. Aquí están mis pensamientos sobre Webpack:

  1. Gestión modular: Webpack admite dividir el código en múltiples módulos y administrarlos a través de dependencias. Puede identificar dependencias entre módulos, crear automáticamente gráficos de dependencia y empaquetar todos los módulos en el archivo de salida final. Esto nos permite organizar el código de forma modular en el proyecto y mejorar la mantenibilidad y reutilización del código.

  2. Potentes capacidades de empaquetado: Webpack no solo admite el empaquetado de archivos JavaScript, sino que también puede manejar otros tipos de archivos, como CSS, imágenes, fuentes, etc. Los cargadores se pueden usar para convertir y procesar varios tipos de archivos, como usar Babel para convertir la sintaxis de ES6+, usar cargadores de estilo para procesar y empaquetar archivos de estilo, etc. Esto proporciona a los desarrolladores una gran flexibilidad y comodidad.

  3. Sistema de complementos: el sistema de complementos de Webpack permite a los desarrolladores ampliarlo y personalizarlo según sus necesidades. Se pueden utilizar muchos complementos proporcionados por la comunidad para optimizar los resultados del empaquetado, generar automáticamente archivos HTML, extraer código común, comprimir código, etc. Al utilizar complementos, podemos afrontar mejor los diferentes escenarios de desarrollo y necesidades de optimización.

  4. Soporte para entornos de desarrollo y producción: Webpack proporciona opciones de configuración para entornos de desarrollo y producción. En el entorno de desarrollo, puede utilizar la función de reemplazo de módulo en caliente (HMR) para actualizar los módulos modificados en tiempo real para mejorar la eficiencia del desarrollo. En un entorno de producción, el código se puede optimizar y comprimir para producir archivos de compilación más pequeños y eficientes.

  5. Gran apoyo de la comunidad: Webpack es una de las herramientas de creación de aplicaciones para usuario más populares que existen, con una comunidad de desarrolladores grande y activa. La comunidad proporciona una gran cantidad de documentos, tutoriales, complementos y herramientas, lo que brinda a los desarrolladores mucho soporte y soluciones de resolución de problemas.

7. La nueva palabra clave define el proceso de una variable.

Al utilizar la nueva palabra clave para crear un objeto, se seguirán los siguientes pasos:

  1. Asigne espacio de memoria: según el tipo de objeto, asigne suficiente espacio en la memoria para almacenar las variables miembro del objeto.
  2. Inicializar variables miembro: inicializa las variables miembro según el tipo de objeto. Si hay un constructor predeterminado, se utilizan los valores predeterminados para la inicialización; si hay un constructor personalizado, se utiliza el constructor para la inicialización.
  3. Ejecutar el constructor: si hay un constructor personalizado, se ejecutará el constructor. El constructor puede completar algunos trabajos de inicialización de objetos, como establecer valores iniciales, asignar recursos, etc.
  4. Devuelve una referencia al objeto: la nueva expresión devuelve una referencia al objeto, que se puede asignar a una variable para su uso posterior.
    Aquí hay un código de muestra:

public class MyClass {
    
    
    private int myVariable;
    
    public MyClass(int value) {
    
    
        myVariable = value;
    }
    
    public int getMyVariable() {
    
    
        return myVariable;
    }
}

public class Main {
    
    
    public static void main(String[] args) {
    
    
        MyClass obj = new MyClass(10);
        System.out.println(obj.getMyVariable()); // 输出:10
    }
}

En el código anterior, new MyClass(10) crea un objeto MyClass y llama al constructor con un parámetro entero para inicializar la variable miembro myVariable. Finalmente, asigne la referencia del objeto a la variable obj y obtenga el valor de myVariable llamando al método getMyVariable().

Supongo que te gusta

Origin blog.csdn.net/qq_53509791/article/details/131673305
Recomendado
Clasificación