Ставь лайк и смотри, поиск в WeChat【Переезд в мир】Обратите внимание на этого человека, который не имеет большого фабричного прошлого, но имеет восходящий и позитивный настрой. эта статья
GitHubGitHub.com/QQ449245884…Он был включен, статьи были классифицированы, и многие мои документы и учебные материалы были систематизированы.
Все говорили, что нет проекта для написания резюме, поэтому я помог вам найти проект, и это было с бонусом.【Учебник по строительству】.
различныйСпособJavaScriptпонимание языка иDOMстепень мастерства.
Давайте начнем! Обратите внимание, что в приведенных ниже примерах мы будем использовать нативный JavaScript, поскольку интервьюеры обычно хотят знать, насколько хорошо вы понимаете JavaScript и DOM без помощи таких библиотек, как jQuery.
Чтобы читать больше качественных статей, пожалуйстаПосетите блог GitHub, Сотни качественных статей ждут вас каждый год!
Проблема 1: делегат события
При создании приложения иногда нужно привязать событие к кнопке, тексту или изображению на странице для выполнения некоторых операций, когда пользователь взаимодействует с элементом.
<ul id="todo-app">
<li class="item">Walk the dog</li>
<li class="item">Pay bills</li>
<li class="item">Make dinner</li>
<li class="item">Code for one hour</li>
</ul>
document.addEventListener('DOMContentLoaded', function() {
let app = document.getElementById('todo-app');
let itimes = app.getElementsByClassName('item');
for (let item of items) {
item.addEventListener('click', function(){
alert('you clicked on item: ' + item.innerHTML);
})
}
})
Хотя это технически возможно, проблема заключается в том, чтобы привязать событие к каждому элементу в отдельности. это для текущего4элемент, ничего страшного, но если добавить в список дел10,000А что насчет элементов (вероятно, у них много работы)?Функция затем создаст 10 000 независимых прослушивателей событий и привяжет каждый прослушиватель событий к DOM, что сделает выполнение кода очень неэффективным.
На собеседовании лучше всего начать с вопроса интервьюеру, какое максимальное количество элементов может ввести пользователь. Например, если он не превышает10, тогда приведенный выше код будет работать нормально. Но если нет ограничений на количество записей, которые может ввести пользователь, вам следует использовать более эффективное решение.
Если ваше приложение может иметь сотни обработчиков событий, более эффективным решением будет фактическая привязка одного обработчика событий ко всему контейнеру, а затем доступ к каждому элементу списка при щелчке по нему, который вызываетсяделегация мероприятия, что более эффективно, чем присоединение отдельного обработчика событий.
Вот код делегата события:
document.addEventListener('DOMContentLoaded', function() {
let app = document.getElementById('todo-app');
app.addEventListener('click', function(e) {
if (e.target && e.target.nodeName === 'LI') {
let item = e.target;
alert('you clicked on item: ' + item.innerHTML)
}
})
})
Проблема 2: использование в замыканиях петли
Замыкания часто появляются на собеседованиях, чтобы интервьюер мог оценить ваше знакомство с JS и знаете ли вы, когда их использовать.
Замыкание — это, по сути, внутренняя функция, которая может обращаться к переменным за пределами своей области видимости. Замыкания могут использоваться для реализации конфиденциальности и создания фабрик функций.
Напишите функцию, которая будет перебирать список целых чисел и печатать индекс каждого элемента после задержки в 3 секунды.
Часто неправильно пишут так:
const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log('The index of this number is: ' + i);
}, 3000);
}
Если вы запустите приведенный выше код,3После второй задержки вы увидите, что фактически каждая распечатка4, вместо ожидаемого0,1,2,3.
Чтобы правильно понять, почему это происходит, было бы очень полезно понять, почему это происходит в JavaScript, а именно это и пытается проверить интервьюер.
Причина в том, чтоsetTimeoutФункция создает функцию (замыкание), которая имеет доступ к своей внешней области видимости, которая является содержащим индекс.iцикл. проходить через3i40,1,2,3,44.
На самом деле естьмногие местаКак правильно решить эту задачу:
const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
setTimeout(function(i_local){
return function () {
console.log('The index of this number is: ' + i_local);
}
}(i), 3000)
}
const arr = [10, 12, 15, 21];
for (let i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log('The index of this number is: ' + i);
}, 3000);
}
Вопрос 3: дроссель и антикровь (отпонствуйте)
Некоторые события браузера могут быстро срабатывать несколько раз за короткое время, например, изменение размера окна или прокрутка страницы вниз. Например, прослушивая страницу события прокрутки окна, и пользователи продолжают быстро прокручивать страницу вниз, тогда события прокрутки могут срабатывать тысячи раз за три секунды, что может вызвать серьезные проблемы с производительностью.
Если вы обсуждаете создание приложения на собеседовании, обязательно упомяните такие события, как прокрутка, изменение размера окна или нажатие клавиш.устранение дребезгаа такжеДросселирование функцийдля повышения скорости и производительности страницы. Суть этих двух братьевЗакрытиеформа существует. Оборачивая функцию обратного вызова, соответствующую событию, кэшируя информацию о времени в виде свободной переменной и, наконец, используя setTimeout для управления частотой срабатывания события.
####Дроссель: последнее слово за первым
Основная идея дросселя такова: в течение определенного периода времени, независимо от того, сколько раз вы запускаете обратный вызов, он будет распознавать только первый раз и давать ответ, когда истечет время таймера.
В этой истории «арбитр» — это наш дроссельный клапан. Он контролирует время приема пищи участниками. Таймер — это информация о времени в форме упомянутых выше свободных переменных. чтобы остановить игру Наконец, ожидание результата игры соответствует выполнению callback-функции.
Подводя итог, можно сказать, что так называемое «регулирование» достигается за счет игнорирования последующих запросов обратного вызова в течение определенного периода времени. Пока судья объявляет о начале игры, судья запускает таймер, в это время участники продолжают есть, и никто не может знать окончательный результат.
То же самое и с реальным взаимодействием: каждый раз, когда пользователь инициирует событие прокрутки, мы запускаем таймер для этого инициирующего действия. В течение определенного периода времени все последующие события прокрутки будут рассматриваться как «участник ест пищу — они не могут запускать новые обратные вызовы прокрутки. Пока не истечет «период», обратный вызов, соответствующий первому инициированному событию прокрутки, не будет выполняться, и Последующие обратные вызовы прокрутки, запускаемые «на некоторое время», игнорируются дросселем.
Теперь реализуем дроссель вместе:
// fn是我们需要包装的事件回调, interval是时间间隔的阈值
function throttle(fn, interval) {
// last为上一次触发回调的时间
let last = 0
// 将throttle处理结果当作函数返回
return function () {
// 保留调用时的this上下文
let context = this
// 保留调用时传入的参数
let args = arguments
// 记录本次触发回调的时间
let now = +new Date()
// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
if (now - last >= interval) {
// 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
last = now;
fn.apply(context, args);
}
}
}
// 用throttle来包装scroll的回调
const better_scroll = throttle(() => console.log('触发了滚动事件'), 1000)
document.addEventListener('scroll', better_scroll)
Сравнение дроссельной заслонки для понимания устранения дребезга: в логике дроссельной заслонки последнее слово остается за судьей.Когда игровое время истекло, выполняется функция обратного вызова. И debounce считает, что последнее слово за последним участником, пока есть еда, новый таймер будет сброшен.
Теперь реализуем debounce вместе:
// fn是我们需要包装的事件回调, delay是每次推迟执行的等待时间
function debounce(fn, delay) {
// 定时器
let timer = null
// 将debounce处理结果当作函数返回
return function () {
// 保留调用时的this上下文
let context = this
// 保留调用时传入的参数
let args = arguments
// 每次事件被触发时,都去清除之前的旧定时器
if(timer) {
clearTimeout(timer)
}
// 设立新定时器
timer = setTimeout(function () {
fn.apply(context, args)
}, delay)
}
}
// 用debounce来包装scroll的回调
const better_scroll = debounce(() => console.log('触发了滚动事件'), 1000)
document.addEventListener('scroll', better_scroll)
Оптимизация дребезга с помощью Throttle
Проблема с отбором заключается в том, что это «слишком терпеливой». Представьте, что операция пользователя очень часто, - он не ждет времени задержки, установленное DELAY, чтобы заканчиваться каждый раз, прежде чем выполнять следующую операцию, поэтому каждый раз отбросит регенерирует таймер для пользователя, функция обратного вызова задерживается бесчисленное отсутствие. Частые задержки приведут к тому, чтобы пользователи получили отсрочку ответов, и пользователи также будут чувствовать себя ощущение «эта страница застряла».
Чтобы избежать саморазрушения, нам нужна идея использовать рычаг газа, чтобы создать «результат» устранения дребезга — так что вы можете, но у меня есть свои принципы: внутреннее время задержки, я могу восстановить таймер для вас; но пока время задержки истекло, я должен дать пользователю ответ. Идея «подгонки» дросселя и устранения дребезга применялась во многих зрелых интерфейсных библиотеках для реализации их расширенной функции дросселя:
// fn是我们需要包装的事件回调, delay是时间间隔的阈值
function throttle(fn, delay) {
// last为上一次触发回调的时间, timer是定时器
let last = 0, timer = null
// 将throttle处理结果当作函数返回
return function () {
// 保留调用时的this上下文
let context = this
// 保留调用时传入的参数
let args = arguments
// 记录本次触发回调的时间
let now = +new Date()
// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
if (now - last < delay) {
// 如果时间间隔小于我们设定的时间间隔阈值,则为本次触发操作设立一个新的定时器
clearTimeout(timer)
timer = setTimeout(function () {
last = now
fn.apply(context, args)
}, delay)
} else {
// 如果时间间隔超出了我们设定的时间间隔阈值,那就不等了,无论如何要反馈给用户一次响应
last = now
fn.apply(context, args)
}
}
}
// 用新的throttle包装scroll的回调
const better_scroll = throttle(() => console.log('触发了滚动事件'), 1000)
document.addEventListener('scroll', better_scroll)
Ссылаться на:
Throttling and Debouncing in JavaScript The Difference Between Throttling and Debouncing Examples of Throttling and Debouncing Сообщение в блоге Реми Шарпа о вызовах функций регулирования Принцип и практика оптимизации производительности интерфейса
Ваши лайки - моя мотивация продолжать делиться хорошими вещами, ставьте лайки!
общаться с
Статья постоянно обновляется каждую неделю. Вы можете выполнить поиск «Big Move to the World» в WeChat, чтобы прочитать и обновить ее как можно скорее (на одну или две статьи раньше, чем в блоге). Эта статья находится на GitHub.GitHub.com/QQ449245884…Он был включен, и многие мои документы были разобраны. Добро пожаловать в Звезду и совершенство. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Кроме того, обратите внимание на паблик-аккаунт и ответьте в фоновом режиме.Благосостояние, вы можете увидеть преимущества, вы знаете.