【Entrevista】Resumen de respuestas y registro de preguntas de la entrevista inicial intermedia

prefacio

Recientemente entrevisté a un ingeniero de desarrollo front-end intermedio de una empresa de Internet. Buen chico, acércate y comienza a escribir preguntas a mano, pruebas de algoritmos, etc.

Por la presente registre las preguntas del examen. Vea si puede ayudar a todos, algunas preguntas se olvidan, registrémoslo a grandes rasgos.

Tabla de contenido

--Preguntas de escritura--

1. La diferencia entre let y var

2. Resultado de la ejecución del bucle de eventos

3. Preguntas sobre algoritmos

4. Promesa de inspección

5. Preguntas de algoritmo, juzgando paréntesis válidos

--Preguntas técnicas--

6. Hable sobre el algoritmo diff

7. El proceso de ingresar la url a la visualización de la página.

9. El proceso de trabajo del paquete web y qué cosas se han utilizado en el paquete web

por fin


1. La diferencia entre let y var

for(sea i = 0; i<5; i++) {

setTimeout(() => consola.log(i),0)

}

Pregunte sobre el resultado de la ejecución y el resultado de la ejecución de cambiar let a var

Mi respuesta:

En ese momento, vi que se basaba en el alcance de nivel de bloque let. Por lo general, me gusta usar bucles let in for, así que básicamente obtuve la respuesta correcta, pero ingresé la cantidad incorrecta de bucles, sin palabras. . .

respuesta correcta:

sea: 0 1 2 3 4

era: 5 5 5 5 5

Analizar gramaticalmente:

var declara una variable global, y luego setTimeout es una función asíncrona.Después de que se completa el bucle, i se convierte en 5, por lo que se emiten cinco 5;

Y sea a nivel de bloque, cada ciclo tiene su propio alcance local, por lo que la salida 0-4

2. Resultado de la ejecución del bucle de eventos

No recuerdo claramente el título, probablemente sean los dos siguientes, probablemente lo escribí yo

setTimeout(function() {
  console.log('1')
  new Promise(function() {
      console.log('2')
  }).then(
    console.log('3')
  )
},0)


new Promise(function() {
  console.log('4')
}).then(
  console.log('5')
)

setTimeout(function() {
  new Promise(function() {
      console.log('6')
  }).then(
    console.log('7')
  )
},0)

respuesta correcta:

guión de inicio 2 3 guión final 1 4

setTimeout(function() {
  console.log('1')
  new Promise(function() {
      console.log('2')
  }).then(
    console.log('3')
  )
},0)


new Promise(function() {
  console.log('4')
}).then(
  console.log('5')
)

setTimeout(function() {
  new Promise(function() {
      console.log('6')
  })
},0)

respuesta correcta:

4 5 1 2 3 6  

Mi respuesta:

La primera respuesta fue muy suave, y luego la segunda se atascó. Estaba un poco confundido en ese momento. El resultado de la primera escritura fue ejecutar todas las tareas macro y luego ir a la cola de tareas micro. Luego me di cuenta que era para ejecutar una macro tarea, y luego ejecutar todas las micro tareas.

Entonces, en ese momento, estaba atascado en si al final era 1263 o 1236. Afortunadamente, finalmente se corrigió.

3. Preguntas sobre algoritmos

Hay una función agregar:

Ejecute add(1)(1+2+3+4) , el resultado es 11

Ejecute add(2)(1+2+3+4) , el resultado es 12

Ejecute add(2)(1+2+3+4+1+1) , el resultado es 14

Por favor escribe la función de suma

Mi respuesta:

En primer lugar, permítanme observar las características de esta función.

Después de observar durante un tiempo, se encuentra que el valor ingresado por segunda vez se suma al valor ingresado por primera vez

Entonces, la función puede ejecutarse continuamente, y es seguro que la función de suma debe devolver un método

Entonces mi respuesta:

Escríbelo por primera vez:

function add(num) {
  let result 
  return function(num,...rest){
    let result = rest.reduce((a,b) => a+b)+n
    return result
  }
}

Para la primera respuesta, sigo mi pensamiento, sumo este último valor al valor anterior, para que este último valor se reciba con el parámetro restante de ... descanso, porque la cantidad de parámetros pasados ​​​​en la segunda vez no es necesariamente la misma, pero el entrevistador recordó que la segunda llamada no pasó num. Por eso me di cuenta que la segunda vez me acaba de pasar el valor de la segunda vez.

Luego, inmediatamente pensé en reemplazar el parámetro resto con argumentos, y luego, el primer número pasado se declara en la función de primer nivel, lo que constituye un cierre, y la función de segundo nivel se puede usar directamente~ Genial

function add(num) {
  let n = num
  return function(){
    let arr = Array.from(arguments)
    let result = arr.reduce((a,b) => a+b)+n
    return result
  }
}

4. Promesa de inspección

var a = Promise.resolve()
var b = Promise.resolve('foo')
var c = Promise.resolve(() => null)
var d = Promise.resolve(() => undefined)
var e = Promise.resolve(() => 'foo')
var f = Promise.resolve(() => Promise.resolve('foo'))
var g = Promise.resolve(() => Promise.reject('err'))
var h = Promise.resolve(() => new Promise(() => {
  Error('err')
}))
console.log(a,b,c,d,e,f,g,h)

Por favor escriba los valores de a, b, c, d, e, f, g, h

Mi respuesta:

Cuando vi esta pregunta, me quedé estupefacto y dije tonterías, la mitad de las respuestas estaban mal.

Respuesta correcta:
Promesa {<cumplido>: indefinido}

Promesa {<cumplida>: 'foo'}

Promesa {<cumplida>: f}

Promesa {<cumplida>: f}

Promesa {<cumplida>: f}

Promesa {<cumplida>: f}

Promesa {<cumplida>: f}

Analizar gramaticalmente:

Explicación detallada de MDN

Promise.resolve()El método devuelve un  objeto Promise que se resuelve con el valor dado. Si el valor es una promesa, esa promesa se devuelve; si el valor es un thenable (es decir, tiene un  método "then" ), la promesa devuelta "seguirá" a ese thenable, tomando su estado final; de lo contrario, la promesa devuelta se cumplirá con el valor. Esta función aplana las capas anidadas de objetos similares a promesas (p. ej., promesas que se resuelven en algo) en una sola capa.

A veces es necesario convertir un objeto existente en un objeto de promesa, y el método Promise.resolve() hace esto.

Promesa.resolve('foo')

Equivalente a

nueva Promesa(resolver => resolver('foo'))

Promise.resolve() tiene cuatro parámetros

El primer tipo: sin ningún parámetro

setTimeout(function () {
  console.log('three');
}, 0);

Promise.resolve().then(function () {
  console.log('two');
});

console.log('one');
// one two three

Equivalente a un objeto de promesa en estado de resolución

El segundo tipo: variables ordinarias u objetos ordinarios

const p = Promise.resolve('Hello');

p.then(function (s){
  console.log(s)
});
// Hello

Equivalente al objeto de promesa del estado de resolución

El tercero: el parámetro es una instancia de Promise

Si el argumento es una instancia de Promise, Promise.resolve devolverá la instancia sin ninguna modificación.

El cuarto tipo: el parámetro es un objeto entoncesable

//thenable对象指的是具有then方法的对象,比如下面这个对象

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};
//Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);
p1.then(function(value) {
  console.log(value);  // 42
});
//thenable对象的then方法执行后,对象p1的状态就变为resolved,
//从而立即执行最后那个then方法指定的回调函数,输出 42

5. Preguntas de algoritmo, juzgando paréntesis válidos

Escriba un método, ingrese una cadena solo con paréntesis, (){}[] [(),{}] {[()]} estos devolverán verdadero

([)] (}) Esto devolverá falso

Mi respuesta:

Cuando vi esta pregunta, pensé para mis adentros: ¡Buen chico, lo he cepillado en Likou y es estable! Pensándolo de nuevo, olvidé cómo hacerlo. . . Zhuo!

Primera respuesta:

Mi idea es juzgar primero si es una cadena vacía o un número par, y excluir casos especiales.

Luego recorra la cadena y juzgue las seis condiciones del elemento ( , ), { , } , [ , ] respectivamente. Por ejemplo, si es un paréntesis izquierdo, su lado derecho debe ser un paréntesis derecho.

¡pero! El entrevistador sugirió que solo se puede juzgar (){}[], entonces, ¿qué pasa con {[()]}?

Segunda respuesta:

Pensé en otra solución de revés, punteros dobles, atravesando dos capas de cadenas, la primera capa es hacia adelante, la segunda capa es hacia atrás y luego, por ejemplo, si la primera capa es un paréntesis izquierdo, la segunda capa debe ser un paréntesis derecho.

¡pero! El entrevistador sugirió que esto solo puede juzgar la situación de {[()]}

Responde por tercera vez:

Zhuo! ! Qué diablos, estoy confundido. De repente tuve una idea y pensé en encontrar los corchetes coincidentes uno por uno, y luego eliminar los corchetes coincidentes de la cadena y finalmente ver lo que queda de la cadena.

En este momento, el entrevistador también me recordó que puedo pensar en cambiar la estructura de datos y considerar usar una pila. De hecho, mi idea es básicamente la misma que la pila, pero no. . .

respuesta correcta:

var isValid = function(s) {
    const n = s.length;
    if (n % 2 === 1) {
        return false;
    }
    const pairs = new Map([
        [')', '('],
        [']', '['],
        ['}', '{']
    ]);
    const stk = [];
    for (let ch of s){
        if (pairs.has(ch)) {
            if (!stk.length || stk[stk.length - 1] !== pairs.get(ch)) {
                return false;
            }
            stk.pop();
        } 
        else {
            stk.push(ch);
        }
    };
    return !stk.length;
};


En este punto, las preguntas de escritura a mano han terminado y luego se hacen algunas preguntas técnicas:

6. Hable sobre el algoritmo diff

Mi respuesta:

1. El algoritmo de diferencias de Vue es comparar desde ambos lados con el nodo medio. Y se usa un puntero doble para actualizar mientras se compara. El algoritmo diff de React se compara de izquierda a derecha. Durante la comparación, los nodos modificados se generan en un árbol de parches y el parche se aplica después de la comparación.

2. El algoritmo de diferencias generalmente necesita especificar la clave del nodo, es decir, el valor único, de modo que la precisión de la comparación de diferencias pueda garantizarse después de eliminar u ordenar el nodo.

3. En comparación con vue2, el algoritmo diff de vue3 está optimizado. Juzgará si cada nodo es un nodo dinámico durante la etapa de compilación. Al verificar si hay símbolos como v-on, :class, etc. en el nodo, y luego recopilará nodos dinámicos para generar un árbol de bloques. Cuando el dom cambie, solo comparará el árbol de bloques. Debido a que vue3 ha realizado mejoras estáticas en los nodos estáticos, los nodos estáticos solo se renderizarán una vez.

4. El algoritmo diff de vue3 también usa patchFlag para marcar nodos dinámicos para determinar de manera más eficiente qué se ha modificado.

7. El proceso de ingresar la url a la visualización de la página.

1. Cuando no se ingresa la URL, busque marcadores, registros de historial, etc., puede solicitar y completar la dirección de manera inteligente

2. Dado que la entrada es un nombre de dominio, primero se debe resolver la dirección IP asignada al nombre de dominio. Por lo tanto, primero se debe realizar la resolución DNS, primero para ver si hay algún caché del navegador, si no, solicitar el servidor DNS local, es decir, el operador local, antes de solicitar el servidor DNS raíz, luego el servidor de nombres de dominio de nivel superior y finalmente el servidor de nombres de dominio autorizado. hasta que lo encuentres.

3. Después de analizar la dirección IP, haga una conexión TCP

4. El proceso de red del navegador inicia una solicitud, un apretón de manos de tres vías para solicitar datos y, después de obtener los datos, agita cuatro veces para liberar la conexión tcp

5. El proceso del navegador del navegador está listo para comenzar a renderizar y, cuando esté listo, el proceso ipc se comunica para notificar al proceso de renderizado que comience a renderizar.

6. El proceso de renderizado comienza a renderizar, primero analiza el html, genera un árbol dom, luego analiza las reglas css, genera un árbol css y luego se combina para generar un árbol de renderizado. En este momento, el árbol de renderizado eliminará la etiqueta de encabezado y el nodo display: none, por lo que no es exactamente igual que la estructura del árbol dom. Diseño final, dibujo.

8. El proceso de trabajo del paquete web y qué cosas se han utilizado en el paquete web

En términos del proceso de trabajo, es posible que no lo haya entendido bien en ese momento y dije algo sobre el árbol de sintaxis abstracta ast. En realidad debería decir esto:

  • compile empezar a compilar
  • make Analice el módulo y sus módulos dependientes desde el punto de entrada, creando esos objetos de módulo
  • build-module bloques de construcción
  • after-compile construcción completa
  • seal Resultados de la compilación del paquete
  • emit Envíe cada fragmento al archivo de resultados
  • after-emit salida completa

Entonces usa lo que dije:

1. Configurar el cargador de svg o algo

2. Mapa fuente abierto

3. Habilitar la compresión gzip

4. Configurar entre dominios

5. Subcontratación

6. Instala el complemento

7. Las bibliotecas de terceros se cargan bajo demanda

por fin

Si hay algo mal o algo que agregar, ¡corríjalo o agréguelo!

Supongo que te gusta

Origin blog.csdn.net/qq_38974163/article/details/124218610
Recomendado
Clasificación