[Pregunta de la entrevista] js-¿El entrevistador requiere aceleración de escritura a mano y antivibración?

  Banco de preguntas de la entrevista inicial ( necesario para la entrevista) recomendación: ★★★★★            

Dirección: banco de preguntas de la entrevista inicial

prefacio

Como programador, la implementación de código es la encarnación de la capacidad. En la mayoría de las entrevistas, se nos pedirá que escribamos código para implementar una función. Esto requiere buenos hábitos e ideas de codificación. A veces, también podemos leer y comprender más. , que es útil. Aquí resumo la realización de las funciones de estrangulamiento y antivibración que a menudo solicitan los entrevistadores , y las comparto con amigos que las necesitan.

anti vibración

Anti-vibración es para evitar que un evento se active con frecuencia y repetidamente. Por ejemplo, cuando hacemos clic en un botón para activar un evento, podemos hacer clic varias veces seguidas, luego la función de evento se activará varias veces seguidas, lo cual es un desperdicio, especialmente para los datos de solicitud asíncrona, lo que afectará en gran medida el rendimiento y la experiencia del usuario. Por lo tanto, anti-vibración significa que la función de evento no se activa nuevamente dentro del tiempo especificado después de que la función se activa una vez, y luego se ejecuta la función de evento.Si se activa repetidamente dentro del tiempo especificado, solo se ejecuta el último activador.

Idea de implementación:

En primer lugar , necesitamos saber que la función antivibración es una función de herramienta. Necesitamos pasar la función de evento objetivo a la función antivibración como parámetro. La función antivibración debe devolver una función que llame al objetivo. Cuando llame a la función antivibración, deje que la función antivibración llame a la función de evento de destino para realizar la función antivibración. En segundo lugar , si comienza desde la perspectiva de un programador intermedio, debe pensar que cuando usamos la función anti-vibración que escribimos como una API para programadores junior, esperamos poder establecer activamente el intervalo de tiempo para anti-vibración, por lo que este intervalo de tiempo también debe ser anti-vibración Un argumento para la función de sacudida.

function debounce(fn,wait){
    return function(){
        fn()
    }
}

En esta función antivibración, debemos llamar a la función de evento de destino entrante. Además, también debemos configurar el tiempo de espera antivibración de acuerdo con los parámetros. Después de activar la función una vez, debemos esperar el intervalo de tiempo. antes de ejecutar la función de evento de destino. Así que pensamos en usar un temporizadorsetTimeout() , llamar a la función de destino y establecer el tiempo de espera. Cuando volvemos a activar la función antivibración dentro del tiempo de espera, debemos borrar el temporizador anterior y esperar el tiempo nuevamente, luego debemos definir un nombre de variable para el temporizador y llamar a la función de borrado del temporizador.

*Nota: La definición del nombre de la variable del temporizador debe estar fuera de la función devuelta para formar un cierre; de ​​lo contrario, cada vez que se activa la función antivibración y se llama a la función de evento de destino, se redefinirá una variable vacía con el mismo nombre. , lo que provoca que no se borre el temporizador anterior

function debounce(fn,wait){
    let timeout
    return function(){
        clearTimeout(timeout)
        timeout = setTimeout(fn,wait)
    }
}

Hasta ahora hemos completado la función general, y luego debemos considerar más detalles que se pueden encontrar al usar esta función anti-vibración:

Por ejemplo, al definir la función de evento de destino, puede usar esto para apuntar a la estructura DOM que activa la función de evento , pero cuando se llama a la función de evento de destino en el temporizador en la función antivibración, cambiará esto en la función para apuntar a la ventana , afectando a la función original, por lo que es necesario corregir este punto de llamar a la función de destino. Por lo tanto, puede usar un enlace explícito (llamar, aplicar, enlazar) para mantener este punto de la función de evento de destino. Cuando el temporizador llama a la función de evento de destino, la función está vinculada a la función antivibración, porque cuando se activa la función antivibración, esto también apunta a la estructura DOM que activó la función.

function debounce(fn,wait){
    let timeout
    return function(){
        clearTimeout(timeout)
        timeout = setTimeout(()=>{ //改成箭头函数,否则不能直接接.call()
            fn.call(this)
        },wait)
    }
}

También es necesario considerar que la propia función de evento de destino definida también puede necesitar pasar parámetros, por ejemplo, puede ser el parámetro de evento e, o puede haber múltiples parámetros. Así que necesitamos deconstruir todas las funciones que la función de evento de destino puede recibir . Al usar la función antivibración para llamar a la función de evento objetivo, solo puede pasar los parámetros que deben pasarse a la función antivibración y luego deconstruir los parámetros de la función antivibración para pasarlos a la función de evento objetivo . argumentsSe usa para representar todos los parámetros aceptados por la función, y podemos usarlo para deconstruir los parámetros recibidos por la función antivibración.

*Nota: argumentses una matriz de clase, que debe deconstruirse y convertirse en una matriz, y luego pasarse a la función de destino como un parámetro. Y la call()función auxiliar recibe parámetros uno por uno, por lo que debemos cambiarla apply()para aceptar matrices como parámetros.

function debounce(fn,wait){
    let timeout
    return function(){
        let args = [...arguments]
        clearTimeout(timeout)
        timeout = setTimeout(()=>{
            fn.apply(this,args)
        },wait)
    }
}

Finalmente, también debemos considerar que la función de evento de destino definida puede tener un valor de retorno, por lo que también debemos definir una variable para recibir el valor de retorno después de la llamada a la función de tiempo de destino y devolver esta variable

function debounce(fn,wait){
    let timeout,result //同样定义在返回函数外,形成闭包
    return function(){
        let args = [...arguments]
        clearTimeout(timeout)
        timeout = setTimeout(()=>{
            result = fn.apply(this,args)
        },wait)
        return result
    }
}

En este punto, se realiza una función antivibración completa, podemos intentar verificarla simplemente, el código fuente:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="btn">0</button>
    <script>
        let count = 0
        let btn = document.getElementById("btn")
        function add(){
            this.innerHTML = ++count
        }
        function debounce(fn,wait){
            var timeout,result
            return function(){
                let args = [...arguments]

                clearTimeout(timeout)
                timeout = setTimeout(()=>{
                    result = fn.apply(this,args)
                },wait)
                return result
            }
        }
        btn.addEventListener('click',debounce(add,1000))
        
    </script>
</body>
</html>

estrangulación

La limitación, similar a la antivibración, es para evitar algunas operaciones innecesarias. La diferencia es que la antivibración es activar repetidamente la función dentro del tiempo especificado, y no se ejecutará hasta que no se active nuevamente dentro del tiempo especificado; y Throttling es activar repetidamente funciones dentro de un tiempo específico, y luego solo una de ellas se ejecutará dentro del tiempo especificado. Por ejemplo, cuando se activa una función de evento de destino al hacer clic, la función se puede ejecutar directamente, pero cuando activamos repetidamente la función varias veces dentro del tiempo especificado, los activadores posteriores no se ejecutarán, y si la función se activa nuevamente después del tiempo especificado, ejecutará la función nuevamente y volverá a calcular el tiempo desde el momento en que se activó esta función, y luego no se ejecutarán los desencadenadores repetidos dentro del tiempo especificado, lo cual es una limitación

Idea de implementación:

La idea de implementación de la limitación es más o menos la misma. Es una función de herramienta que necesita pasar la función de evento de destino y el tiempo especificado como parámetros, y devuelve una función para llamar a la función de evento de destino. Sin embargo, no es necesario para usar un temporizador aquí, y se necesita definir una hora de inicio setTimeout()Cuando Al hacer clic para activar una función, la hora actual se asigna a la hora de inicio, y luego cada activador juzga si el intervalo de tiempo desde el inicio excede el tiempo especificado. Si se supera, se ejecuta la función y se asigna la hora actual a la hora de inicio, si no se supera, no se ejecuta la función y no se reasigna la hora de inicio

function throttle(fn,wait){
    let preTime = 0  //同样使用闭包,保留这个变量
    return function(){
        let now = +new Date()  //一元运算符+改为秒数时间
        if(now - preTime > wait){
            fn()
            preTime = now
        }
    }
}

Además, también es necesario considerar el puntero this en la función de evento de destino, así como los parámetros que la propia función de evento de destino necesita recibir y el posible valor de retorno. Vale la pena señalar que aunque setTimeout()el temporizador no se usa aquí, el punto interno de la llamada de función también se cambiará y se verá afectado en la función devuelta, por lo que es necesario usar la apply()función auxiliar para mostrar el enlace y corregir este punto.

function throttle(fn,wait){
    let preTime = 0,result
    return function(){
        let args = [...arguments]
        let now = +new Date()
        if(now - preTime > wait){
            result = fn.apply(this,args)
            preTime = now
        }
        return result
    }
}

En este punto, la implementación manuscrita de la función de aceleración también se ha completado, puede probarla, el código fuente:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="btn">0</button>
    <script>
        let count = 0
        let btn = document.getElementById("btn")
        function add(){
            this.innerHTML = ++count
        }
        function throttle(fn,wait){
            let preTime = 0,result
            return function(){
                let args = [...arguments]
                let now = +new Date()
                if(now - preTime > wait){
                    result = fn.apply(this,args)
                    preTime = now
                }
                return result
            }
        }
        btn.addEventListener('click',throttle(add,1000))
    </script>
</body>
</html>

Resumir

En la entrevista, a menudo se encuentra que las funciones deben escribirse a mano, y las funciones anti-vibración y estrangulamiento son una de las funciones que a menudo deben escribirse. No debería resultarle difícil. Por supuesto, escribir it out también es para ayudar a los amigos que lo necesitan. , espero que todos ganen algo, y la entrevista se gane de una sola vez

  Banco de preguntas de la entrevista inicial ( necesario para la entrevista) recomendación: ★★★★★            

Dirección: banco de preguntas de la entrevista inicial

Supongo que te gusta

Origin blog.csdn.net/weixin_42981560/article/details/132026394
Recomendado
Clasificación