предисловие
У автора два года опыта фронтенда.Был фронт-ендом около месяца.За этот период познакомился со многими компаниями,такими как有赞,涂鸦智能,滴滴,字节,酷家乐
大搜车,海康威视,税友Подождите, разберитесь с некоторыми вопросами, исходя из того, что мне задавали на личном собеседовании (包括但不限于).
Перед началом собеседования также очень важно отличное резюме.Рекомендуются две статьи:Как должно выглядеть хорошее резюме разработчика интерфейса?,Как написать «внешнее резюме», чтобы постучать в дверь ByteDance?
Чтобы получить более удовлетворительное предложение, я выбрал несколько малых и средних компаний, чтобы практиковать свои навыки за неделю до этого. Позже я обнаружил, что слишком маленькие компании не давали эффекта обучения, поэтому через неделю, Я стал рассылать резюме на более крупные фабрики.
Больше всего впечатляет酷家乐, одна сторона удалённая, а потом другая сторона приглашает на место, на месте это три раунда тех.+час, около трёх часов, и оперативность очень высокая, но первое собеседование так затянулось (я не не знаю, это заняло бы так много времени в то время), в результате чего позднее исполнение Не очень хорошо, то умер.涂鸦智能Оперативность тоже очень высокая, процесс собеседования такой же, как и у Куджиале, все дистанционно, три раунда выездной техники + час. Другие компании в основном проходят раунд за раундом, и результаты каждого раунда, как правило, вам сообщают на следующий день, конечно, если вы не можете ждать через несколько дней, это тоже своего рода уведомление.
HTTP
Вопрос про http - горячий вопрос на собеседовании. Я люблю задавать его в какой-то кроссфейс или в одну сторону. Это проверка вашего владения основами.
В чем разница между get и post?
параметры запроса: параметры запроса на получение передаются через URL-адрес, а несколько параметров связаны с запросами &; POST, помещаемыми в тело запроса.
кеш запроса: запросы на получение будут кэшироваться, а запросы на отправку — нет, если только они не установлены вручную.
относительная безопасность:get передает параметры через URL-адрес, который кэшируется браузером и может быть легко получен другими пользователями. Post относительно безопасен.
Ограничение длины параметра запроса: get передает параметры через URL-адрес, и браузер ограничит длину URL-адреса (http不会).
Кодирование: запросы GET могут быть закодированы только в URL-адресе, тогда как POST поддерживает несколько методов кодирования.
В чем разница между http1.1 и http2.0?
(включая, помимо прочего, сравнение версий 1.1 и 2.0)
http1.1
- Введена постоянная ссылка, то есть TCP не закрыт по умолчанию и может повторно использоваться несколькими запросами.
- Представьте конвейерный механизм, TCP-соединение может отправлять несколько запросов одновременно.
- Добавлены некоторые кешированные поля
- Добавлены методы PUT, DELETE, OPTIONS, PATCH
- Поддерживает возобновление передачи с точки останова, что достигается через поле заголовка запроса Rang.
http2.0
- сжатие заголовка
- мультиплексирование
- Двоичная передача, информация заголовка и тело данных являются двоичными
- Приоритет запроса, установите приоритет фрейма данных, пусть сервер обработает его первым
- Сервер активно отправляет сообщение
Некоторые заданные вопросы:
- Какие проблемы вызовет конвейерный механизм и как их решает http2.0?
- В чем принцип сжатия заголовков
- Роль метода опционов
- http2.0 позволяет серверу активно отправлять сообщения, отличается ли это от WebSocket?
Порекомендуйте статью боги Саньюань:Душа HTTP, укрепите свою систему знаний HTTP
Разговор о http-кэшировании
подожди, пока не закончишь强缓存а также协商缓存Общий процесс, который интервьюер может основывать на ваших ответах, чтобы глубоко изучить ваше понимание кэширования http, например (включая, но не ограничиваясь):
Должен ли сервер возвращать код состояния 200?
Нет, при попадании в сильный кеш ресурс будет прочитан непосредственно из памяти или с диска, и будет возвращен код состояния 200. Для определенных операций вы можете попробовать использовать клавиши браузера вперед и назад.
Как директивы max-age Expires и Cache-Control определяют время истечения срока действия соответственно? Какие преимущества и недостатки?
Зачем ETag с Last-Modified? В чем проблема?
В чем смысл no-store и no-cache соответственно?
Порекомендуйте статью, отвечающую на эти вопросы:Картинка для понимания http кэширования
Почему https безопаснее, чем http
Интервьюер попросит вас сказать, что делает https, и тогда он не исключит принцип шифрования. (ps: байтовый интервьюер спросил)
В основном используются симметричное шифрование и асимметричное шифрование.Рекомендуемая литература:Тщательно понять принцип шифрования HTTPS
Скажи три рукопожатия четыре раза
Этот вопрос редко задают и встречаются только один раз. Рекомендовать статью, написанную автором ранее:Трехстороннее рукопожатие TCP, четыре волны
JS
0,1 + 0,2 !== 0,3? Почему?
-
二进制转换: Когда js выполняет цифровые вычисления, нижний слой преобразуется в двоичный для вычислений. 0,1 в двоичный — это десятичное число с бесконечным циклом, поэтому 0,2, но js используетДвоичная арифметика с плавающей запятой IEEE754, который фактически может хранить до 53 значащих цифр, поэтому точность теряется. -
对阶运算: Мантисса с малым порядком должна быть сдвинута вправо на разность шагов.При смещении мантиссы может быть потеряно число и пострадает точность.
Как решить проблему потери точности, упомянутую выше?
- В начале первой реакцией было разложить десятичную точку до целого числа, а после сложения разделить обратно. (Неуместно, потому что это все еще может превышать максимальное количество js)
- Используйте сторонние библиотеки, такие как
Math.js,big.jsЖдать - Воспользуйтесь преимуществами новых базовых типов данных в ES2020BigInt
- Преобразуйте их в строки, а затем добавьте две строки (реализованы рукописные вопросы)
Закрытие
- Скажите, в чем суть замыкания? Какие проблемы это вызовет
- Помимо возврата функции внутри функции, есть ли другой способ сгенерировать замыкание? (имеют)
// 函数内部延迟调用,产生了闭包
function test () {
let name = 'tom'
setTimeout(() => {
console.log(name)
}, 2000)
}
test();
рекомендуемая статья:Статическая цепочка областей действия JavaScript и «динамическая» цепочка закрытия
Что такое масштаб? Что такое цепочка областей видимости? Что содержит контекст выполнения функции?
это указывает на
Интервьюер спросил: этот пункт JS
проблема es6
- Отличие стрелочных функций от обычных функций
- Что такое временная мертвая зона и что такое переменное продвижение
- Разница между for of и for in, как for of может пройти через объект?
- Разница между Map es6 и WeakMap, какую проблему решает WeakMap?
- обещание, какие методы находятся в прототипе, а какие в экземпляре
Рекомендуем учебник Учителя Янь Фэна:Учебник по входу в ES6
Прототип + цепочка прототипов (это обязательно)
Пока проблема может быть четко описана, как объект находит свою ценность, в основном понятна половина ее.
Объясните схему выше:
-
prototypeявляется свойством, зависящим от функции,__proto__это свойство, которым обладает каждый объект, иprototypeобъект сам по себе - когда мы идем, чтобы получить
a.nameПри , поиск будет начинаться с собственных свойств объекта, если нет, то он будет искаться сa.__proto__Погляди - объект
a.__proto__указать на функцию-конструкторtestизprototype(прототип), поэтому изa.__protoПоиск атрибутов на самом деле находится вtest.prototypeищет недвижимость, ноprototype(Прототип) сам по себе является объектом, в этом случае будут повторяться два вышеуказанных шага, и в итоге все будут найденыObjectэта функция-конструктор, аObject.__protoЭто нулевое значение, если в середине есть значение, оно будет возвращено, а если значения нет, оно будет присвоеноundefined. - Такая цепная структура является прототипом цепи.
потому что прототип функции конструктораconstructorуказывает на саму функцию-конструктор, поэтому
a.constructor === test // true
a.__proto__.constructor === test // true
a.__proto__.constructor === test.prototype.constructor// true
Есть вопрос интервью, чтобы проверить, сказать, что печатать, и объяснить, почему.
function test () {
}
test.prototype.then = function () {
console.log('test => then')
}
Function.prototype.mythen = function () {
console.log('Function => mythen')
}
test.mythen();
test.then();
eventLoop
Интервьюер будет задавать вопросы на основе ваших ответов, например:
- Вы только что сказали, что js — это один поток, в чем разница между потоком и процессом?
- Браузер открывает новую страницу, сколько там потоков?
- Почему он должен быть спроектирован так, чтобы сначала выполнялись микрозадачи, а потом макрозадачи.
Посоветуйте статью крутого парня:На этот раз досконально изучите механизм выполнения JavaScript.
механизм сбора мусора
- Каковы недостатки метода маркировки, о котором вы только что упомянули? Как с этим бороться?
- Есть ли недостатки у метода подсчета ссылок, который вы только что упомянули?
- Что такое механизм восстановления мусора в V8?
- Как v8 решает циклические ссылки?
рекомендуемая статья:Вы действительно понимаете механизм сборки мусора?
Разговор о типе данных, как судить о массиве
Как оценить массив:
- Array.isArray(arr); // true
- arr instanceof Array; // true
- arr.constructor === Array; // true
- Object.prototype.toString.call(arr); // "[object Array]"
ps: Судя по экземпляру и конструктору, не обязательно точно, потому что он может быть переписан.
Часто используемая модель проектирования?
- Что такое абстрактный заводской шаблон
- В чем разница между шаблоном публикации подписки и шаблоном наблюдателя
- Какие шаблоны проектирования вы используете в своем проекте?
рекомендуемая статья:Шаблоны проектирования, которые необходимо освоить во внешнем интерфейсе
процесс рендеринга в браузере
В общем, я объясню процесс, опираясь на эту картинку.
Некоторые вопросы, заданные интервьюером:
- Будет ли тег ссылки блокировать отображение страницы? Скажи мне почему?
- Почему css рекомендуется вверху, а js внизу?
- Будет ли js блокировать рендеринг страницы? Скажи мне почему?
- Будет ли css блокировать синтаксический анализ html? Почему?
- Будет ли css блокировать рендеринг html? Почему?
js выполняется в отдельном потоке, рендеринг в браузереGUIЗа это отвечает поток рендеринга, а эти два потока взаимоисключающие, поэтому понятно, что js будет блокировать рендеринг страницы.
css не будет блокировать парсинг html, парсинг html и парсинг css идут параллельно, но css будет блокировать отрисовку html, потому что при отрисовке страницы ее нужноstyle Rules + DOM TreeСинтезировать вместеRender Tree.
Обычно, если в процессе парсинга страницы встречается тег скрипта, парсинг HTML будет остановлен (как показано на рисунке ниже), скрипт будет загружен, скрипт будет выполнен сразу после завершения загрузки, и затем HTML будет проанализирован, поэтому, если скорость загрузки скрипта очень низкая, это вызовет белый экран на странице.
defer: парсинг HTML и загрузка скрипта выполняются параллельно (асинхронно), после парсинга HTML,DOMContentLoadedВыполнить скрипт перед запуском.
async: парсинг HTML и загрузка скрипта выполняются параллельно (асинхронно), скрипт выполняется сразу после загрузки, а парсинг HTML прерывается.
Рекомендуемое чтение:
Как работают браузеры: за кулисами современных веб-браузеров,
Посмотрите на процесс рендеринга в браузере и оптимизацию производительности из 8 вопросов интервью.
оптимизация производительности
Обычно я отвечаю с http-запроса + уровень кода + инструменты сборки.
Есть ли разница между setTimeout и requestAnimationFrame для анимации? Какой из них лучше? Почему?
Есть разница:
- точность
setTimeoutАнимация неточная, потому что это задача макроса, и установленное время задержки не равно выполнению сразу после времени задержки, потому что необходимо дождаться завершения задачи синхронизации и микрозадачи перед выполнением задачи макроса, в котором легко потерять кадры;requestAnimationFrameОн выполняется перед отрисовкой элемента в каждом кадре, что является более точным.
- лучшая производительность
Когда скрытые элементы или элементы не видны,
setTimeoutпо-прежнему выполнять задачи анимации в фоновом режиме; в то время какrequestAnimationFrameАнимация остановится, что означает меньшее потребление ресурсов ЦП и памяти.
Как насчет политики того же происхождения? Вы знаете эти междоменные методы? Вы когда-нибудь понимали принцип cors cross-domain?
CSS
Познакомить с коробочной моделью?
Что означает flex: 1
Вы использовали гибкую верстку? Какие свойства есть?
Расскажите, что такое BFC, для чего вы его вообще используете и какую проблему он решает?
Чтобы добиться горизонтального и вертикального центрирования элементов? Назовите как можно больше способов?
Левая фиксированная + правая адаптивная раскладка? Расскажите о нескольких вариантах?
Перерисовывать и перерисовывать?
рекомендуемая статья:Перекомпоновать и перекрасить
React
Пройдя круг, я обнаружил, что реагируют примерно так же.
Вы использовали эти версии реакции, пожалуйста, укажите разницу?
Говоря о внешней маршрутизации, каковы принципы их реализации?
хэш-маршрутизация: слушаяhashchangeСобытия для фиксации изменений URL-адреса, чтобы решить, следует ли обновлять страницу.
исторический маршрут: главный мониторpopState,pushState,replaceStateпринять решение об обновлении страницы. Обратите внимание, однако, что только вызовpushStateметод илиreplaceStateметод, не вызываетpopStateсобытие, только если пользователь нажимает кнопки браузера назад и вперед или вызывается с помощью JavaScriptback,forward,goметод будет запущен только тогда, когда вы хотитеpushState,replaceStateсрабатывать, когдаpopStateсобытие, требуется пользовательское событие.
Можете ли вы написать простой редукс вручную?
После того, как интервьюер закончил говорить, он протянул мне ручку и бумагу... (внутренний коллапс) После написания интервьюер попросил меня рассказать ему еще раз.
function createStore(reducer) {
let listeners = [];
let currentState;
function getState() {
return currentState
}
function dispatch(action) {
currentState = reducer(currentState, action);
listeners.forEach(l => l());
}
function subscribe(fn) {
listeners.push(fn);
return function unsubscribe() {
listeners = listeners.filter(l => l !== fn);
}
}
return {
getState,
dispatch,
subscribe
}
}
Как диспетчер в редуксе правильно находит редуктор?
Да редукс его не ищет, шаттл, каждая отправка должна пройти через все редукторы...
Как redux монтирует промежуточное ПО? Каков порядок его выполнения?
основная функцияcompose
function compose(middlewears) {
return middlewears.reduce((a, b) => (...argu) => a(b(...argu)))
}
Порядок выполнения: промежуточное ПО redux выполняется сзади наперед.
Использовали ли вы какую-либо другую библиотеку управления состоянием, кроме redux?
нет.
Недостатки редукции?
реагировать на жизненный цикл?
Когда setState синхронен, а когда асинхронен?
Расскажите о механизме событий реакции, почему он разработан таким образом? Что-то изменилось в реакции 17?
рекомендуемая статья:Понять принцип системы реагирования на события в одной статье
Преимущества дизайна:
- Сгладьте различия между браузерами для лучшей кроссплатформенности
- Чтобы избежать сборки мусора, React вводит пул событий, получает или освобождает объекты событий в пуле событий и избегает частого создания и уничтожения.
- Обеспечить унифицированный механизм управления событиями и транзакциями
В чем разница между компонентами класса и компонентами функций?
Можете ли вы написать хуки в решении if? Почему бы нет?
Хуки используют связанный список для сохранения состояния. Каждый раз при рендеринге вы должны следить за тем, чтобы длина и порядок хуков были одинаковыми. Если они несовместимы, реакция не может получить правильное состояние и сообщит об ошибке.
В чем разница между HOC и хуками?
Как работают крючки? Есть ли другой способ сделать это без связанного списка?
На основе связанного списка его также можно смоделировать с помощью массива.
Есть ли разница между useEffect, полагающимся на передачу пустого массива, и componentDidMount?
Разница между useeffect и useLayouteffect
-
useEffectне блокирует рендеринг браузера иuseLayoutEffectзаблокирует рендеринг браузера. -
useEffectбудет выполняться после рендеринга браузера,useLayoutEffectвDOMПосле завершения обновления браузер выполняется перед рисованием.
Представьте реакцию dom diff
Представить Вдом?
Была ли оптимизация производительности в React?
Согласно мыслям в голове, я сказал несколько.
рекомендуемая статья:8 способов оптимизировать производительность React
Есть ли разница между React.memo() и React.useMemo()?
Подключитесь к вопросу, а затем к интервьюеру: есть ли разница между ними?
Перейти непосредственно на официальный сайт:React.memo,React.useMemo
Разница между useCallback и useMemo?
То же, что и вышеОфициальный адрес сайта
React.fiber понимаете? В чем причина Катона? Как это решается в react.fiber? После прерывания обновления, как найти место для обновления в следующий раз?
Рекомендуемые статьи бесплодных холмов:Это, пожалуй, самый распространенный способ открыть React Fiber (разрезка по времени)
функциональное программирование
Говоря о хуках, скорее всего спросят о функциональном программировании? (спросил несколько раз)
- Расскажите, как вы понимаете функциональное программирование?
- Какие библиотеки используют идеи функционального программирования?
- Является ли lodash настоящей библиотекой функционального программирования?
Краткий обзор функционального программирования на JavaScript — учебник для начинающих
Как предотвратить потерю ref в компонентах более высокого порядка?
React.forwardRef, адрес официального сайта:React.forwardRef
webpack && node
- Для чего вы использовали узел? Вы использовали структуру узла?
- Node некоторые базовые API, как удалять файлы, создавать файлы, записывать файлы.
- Какие модули узла вы использовали?
разница между процессом и потоком
Познакомить с историей разработки модулей
проблема с node_modules
Предположим, npm устанавливает модуль A, зависящий от версии 0.0.1 c, и устанавливает модуль B, зависящий от версии 0.0.2 c. Как node_module гарантирует, что A и B правильно найдут соответствующую C-версию пакета?
принцип упаковки webpack
- Параметры инициализации: чтение и объединение параметров из файлов конфигурации и операторов оболочки для получения окончательных параметров;
- Начать компиляцию: Инициализировать объект Compiler с параметрами, полученными на предыдущем шаге, загрузить все настроенные плагины и выполнить метод запуска объекта, чтобы начать компиляцию; Определить запись: Найти все файлы записей в соответствии с записью в конфигурации
- Компиляционный модуль: начиная с файла ввода, вызовите все настроенные погрузчики, чтобы скомпилировать модуль, а затем найти модули, которые зависят от модуля, а затем повторяют этот шаг, пока на этом этапе будут обрабатываться все входные файлы;
- Завершение компиляции модуля: после перевода всех модулей с помощью загрузчика на шаге 4 получается окончательное содержимое каждого модуля и зависимости между ними Выходные ресурсы: в соответствии с зависимостями между записью и модулем, сборка в Каждый фрагмент содержит несколько модулей, а затем преобразовать каждый фрагмент в отдельный файл и добавить его в список вывода.Этот шаг — последний шанс изменить содержимое вывода.
- Вывод завершен: после определения содержимого вывода определите путь вывода и имя файла в соответствии с конфигурацией и запишите содержимое файла в файловую систему.
Как вы оптимизируете производительность веб-пакета?
рекомендуемая статья:Позвольте вам подробно разблокировать серию Webpack (оптимизация)
В чем разница между загрузчиком и плагином?
- загрузчик (преобразование): В основном для функций преобразования, таких как преобразование файлов css и less в js, определение различных суффиксов файлов и расширение загрузчика, с которым вы более знакомы.
- плагин (плагин): Принцип состоит в том, чтобы отслеживать некоторые хуки в процессе создания веб-пакета, а затем выполнять некоторые собственные операции и многое другое, чтобы обогатить функции веб-пакета.
Каков порядок выполнения загрузчиков? Как написать загрузчик? Как написать плагин? Загрузчик асинхронный?
Порядок выполнения справа налево, снизу вверх.
Загрузчик по сути функция, а плагин по сути класс.Как его написать?Рекомендуемые статьи:Научу как написать загрузчик/плагин
Загрузчики бывают синхронными и асинхронными.
Что возвращает загрузчик файлов?
Возврат представляет собой строку, см. подробности:исходный адрес загрузчика файлов
В webpack есть несколько видов хэшей, в чем между ними разница? Какой хэш вы обычно используете в своем проекте?
-
hash: это хеш-значение всего проекта, которое рассчитывается в соответствии с содержимым каждой компиляции, и после каждой компиляции будет генерироваться новый хеш, то есть изменение любого файла приведет к изменению хэша всех файлов. -
chunkHash: В соответствии с разными входными файлами (Entry) анализируется файл зависимостей, создается соответствующий фрагмент и генерируется соответствующее хеш-значение (из того же фрагмента значение хеш-функции такое же). -
contentHash: генерировать хеш-значение в соответствии с содержимым файла, такое же хеш-значение совпадает с содержимым файла.
Что нового в вебпак5?
рекомендуемая статья:Практическая оценка Webpack5 командой Feishu
Принцип горячего обновления Webpack?
рекомендуемая статья:Легко понять принцип горячего обновления веб-пакета
Принцип встряхивания деревьев?
использоватьES ModuleПроведите статический анализ, поддерживайте область действия для каждого модуля, анализируя синтаксическое дерево ast, собирайте переменные, используемые внутри модуля, а затем анализируйте область действия, помещайтеimportВходящие неиспользуемые модули удаляются, и, наконец, файлы обрабатываются рекурсивно.
В процессе преобразования кода babel, когда стрелочная функция преобразуется в обычную функцию, как она с этим справляется?
Процесс: парсер => трансформация => генератор, можно расширять и говорить по своему разумению.
Как быть с этим, когда стрелочная функция преобразуется в обычную функцию: найдите это в верхней области видимости, кэшируйте это с уникальным именем переменной, а затем замените это в предыдущей стрелочной функции на это.
рукописные вопросы
троттлинг и стабилизация
(Компания-единорог) Интервьюер: Можете ли вы написать функцию дросселя вручную? Потом дал мне ручку и бумагу...
Функция защиты от тряски
определение: В течение n секунд функция будет запущена только один раз, и если она будет запущена в течение этого периода, она будет повторно рассчитана.
Сцены:input框实时搜索,浏览器的resize,а такжеscroll
function debounce (fn, delay) {
let timer;
return function (...argu) {
let that = this;
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(that, argu);
}, delay);
}
}
регулирование функции
определение: За n секунд событие выполняется только один раз, и если оно срабатывает в течение периода, оно не будет реагировать на событие.
Сцены:表单重复提交,滚动加载
// 利用时间戳实现
function throttle(fn, delay) {
let previous = new Date();
return function (...argu) {
let nowDate = new Date();
if (nowDate - previous > delay) {
fn.apply(this, argu);
previous = nowDate;
}
};
}
// 利用定时器实现
function throttle(fn, delay) {
let timer;
return function (...argu) {
let that = this;
if (timer) return false;
timer = setTimeout(() => {
fn.apply(that, argu);
timer = null; // 释放timer变量,让下一次的函数接着执行
}, delay);
};
}
Напишите сорт, с которым вы знакомы?
Правильно, я тоже написал его ручкой, а после того, как закончил, передал ему свои идеи. Я выбрал быструю сортировку
// 先选一个数当作基点,一般选择最后一个数
// 然后遍历arr, 找出这个基点数的比它大的数组集合和比它小的数组集合
// 递归此步骤
function quickSort(arr) {
if (arr.length < 2) {
return arr;
}
const cur = arr[arr.length - 1];
let left = [];
let right = [];
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i] >= cur) {
right.push(arr[i])
} else {
left.push(arr[i])
}
}
return [...quickSort(left), cur, ...quickSort(right)];
}
console.log(quickSort([1, 3, 3, 6, 2, 4, 1]));
(байты) сказать порядок печати
Нестрогий режим по умолчанию
function Foo() {
getName = function () { alert(1); };
return this;
}
Foo.getName = function () { alert(2); };
Foo.prototype.getName = function () { alert(3); };
var getName = function () { alert(4); };
function getName() { alert(5); }
// 请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
Правильный порядок вывода: 2 4 1 1 2 3
-
Foo.getName(); это ничего не говорит, выход 2 -
getName(); проверить var и продвижение функции, приоритет функции больше, чем var, поэтому выведите 4 -
Foo().getName();Foo() возвращает это, в это время this указывает на окно, Foo().getName эквивалентно window.getName. Но Foo() снова переназначает getName в окне, поэтому вывод равен 1. -
getName(); то же, что и выше, вывод 1 -
new Foo.getName(); посещениеприоритет оператора, new не имеет списка параметров, соответствующий приоритет равен 19; оператор доступа к члену.new (Foo.getName)() -
new Foo().getName().new Foo()Foo.prototype.getName
function myInstanceOf(left, right) {
if (left === null || typeof left !== 'object') return false;
if (typeof right !== 'function') throw new Error('right must be function')
let L = left.__proto__;
let R = right.prototype;
while(L !== null) {
if (L === R) return true;
L = L.__proto__;
}
return false;
}
-
__proto__prototype this
function myNew (context, ...argu) {
let obj = Object.create(null);
obj.__proto = context.prototype;
let res = context.apply(obj, argu);
return typeof res === 'object' ? res : obj;
}
let a = "123456789012345678";
let b = "1";
function add(a ,b){
//...
}
add(a, b) // '123456789012345679'
let a = "123456789012345678";
let b = "1";
// 1. 先找出最大的长度的数
// 2. 给较小的数填充向前填充0
function add(a ,b){
let maxLength = Math.max(a.length, b.length);
a = a.padStart(maxLength, '0');
b = b.padStart(maxLength, '0');
// 123456789012345678
// 000000000000000001
let res = ''; // 返回的值
let sum = 0; // 同位相加的和
let t = 0; // 同位相加和的十位数
let r = 0; // 同位相加和的个位数
for(let i = maxLength - 1; i >= 0; i--) {
sum = parseInt(a[i]) + parseInt(b[i]) + t;
t = Math.floor(sum / 10) // 拿到十位数的值
r = sum % 10; // 拿到个位数的值
res = r + res;
}
return res;
}
console.log(add(a, b)); // 123456789012345679
function flat(arr, depth = 1) {
return depth > 0 ?
arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flat(cur, depth - 1) : cur);
}, []) :
arr.slice();
}
class EventEmitter {
constructor(){
}
// 监听事件
on(){
}
// 触发事件
emit(){
}
// 只监听一次,下次emit不会触发
once(){
}
// 移除事件
off(){
}
}
const events = new EventEmitter();
events.on('hobby', (...argu) => {
console.log('打游戏', ...argu);
})
let eat = () => {
console.log('吃');
}
events.once('hobby', eat);
events.on('hobby', (...argu) => {
console.log('逛街', ...argu);
})
events.off('hobby', eat);
events.emit('hobby', 1,2,3);
events.emit('hello', 'susan')
//打游戏 1 2 3
// 逛街 1 2 3
class EventEmitter {
constructor() {
this.events = {}; // 存放着所有的事件{eventName: [callback, ...]}
}
on(eventName, callback) {
if(!this.events[eventName]) {
this.events[eventName] = [callback];
} else {
this.events[eventName].push(callback);
}
}
emit(eventName, ...argu) {
if(this.events[eventName]) {
this.events[eventName].forEach(fn => fn(...argu))
}
}
off(eventName, callback) {
if(this.events[eventName]) {
this.events[eventName] = this.events[eventName].filter(fn => callback !== fn && fn.l !== callback);
}
}
once(eventName, callback) {
const _once = () => {
callback();
this.off(eventName, _once)
}
_once.l = callback;
this.on(eventName, _once)
}
}
// 接收一个number,返回一个string
function format(number) {
}
console.log(format(12345.7890)); // 12,345.789,0
console.log(format(0.12345678));// 0.123,456,78
console.log(format(123456)); // 123,456
,,
function format (number) {
let str = number.toString();
let [int, dec = ''] = str.split('.');
let intStr = ''
for (let i = int.length - 1; i >= 0; i--) {
if ((int.length - i) % 3 === 0 && i !== 0) {
intStr = ',' + int[i] + intStr;
} else {
intStr = int[i] + intStr;
}
}
let decStr = '';
if (dec.length > 0) {
for (let i = 0; i < dec.length; i ++) {
let sum = decStr + dec[i];
if ((i + 1 )% 3 === 0) {
decStr = sum + ',';
} else {
decStr = sum;
}
}
}
return decStr.length > 0 ? `${intStr}.${decStr}` : `${intStr}`;
};
/**
* @description: 根据传入的姓名权重信息,返回随机的姓名(随机概率依据权重)
* @param {Array} personValue
* @returns {String} personName 姓名
*/
var getPersonName = function (personValue) {
}
const person = [
{
name: '张三',
weight: 1
},
{
name: '李四',
weight: 10
},
{
name: '王五',
weight: 100
}
]
function getResult(count){
const res = {}
for(let i = 0; i < count; i++){
const name = getPersonName(person)
res[name] = res[name] ? res[name] + 1 : 1
}
console.log(res)
}
getResult(10000)
var getPersonName = function (personValue) {
// 标记区间,并且获得weight的总数
let sum = personValue.reduce((pre, cur) => {
cur.startW = pre;
return cur.endW = cur.weight + pre
}, 0);
let s = Math.random() * sum; // 获得一个 0 - 111 的随机数
// 判断随机数的所属区间
let person = personValue.find(item => item.startW < s && s <= item.endW);
return person.name;
}
Promise.all = function (promises) {
let result = [];
let count = 0;
return new Promise((resolve, reject) => {
promises.forEach((p, index) => {
// 兼容不是promise的情况
Promise.resolve(p).then((res) => {
result[index] = res;
count++;
if(count === promises.length) {
resolve(result)
}
}).catch((err) => {
reject(err);
})
})
});
}
var twoSum = function(nums, target) {
let len = nums.length;
let map = new Map();
for(let i = 0; i < len; i++) {
if (map.has(target - nums[i])) {
return [map.get(target - nums[i]), i]
} else {
map.set(nums[i], i)
}
}
};
console.log(twoSum([2,7,11,15], 9))
var lengthOfLongestSubstring = function(s) {
let arr = [];
let max = 0;
for (let i = 0; i < s.length; i++) {
let index = arr.indexOf(s[i])
if (index !== -1) {
arr.splice(0, index + 1);
}
arr.push(s.charAt(i));
max = Math.max(arr.length, max);
}
return max;
};
new Queue()
.task(1000,()=>console.log(1))
.task(2000,()=>console.log(2))
.task(3000,()=>console.log(3)).start();
实现一个Queue函数,调用start之后,1s后打印1,接着2s后打印2,然后3s后打印3
function sleep(delay, callback) {
return new Promise((resolve, reject) => {
setTimeout(() => {
callback();
resolve()
}, delay);
})
}
class Queue {
constructor() {
this.listenser = [];
}
task(delay, callback) {
// 收集函数
this.listenser.push(() => sleep(delay, callback));
return this;
}
async start() {
// 遍历函数
for (let l of this.listenser) {
await l()
}
}
}
new Queue()
.task(1000,()=>console.log(1))
.task(2000,()=>console.log(2))
.task(3000,()=>console.log(3)).start();