Воспроизвести опыт гигантского интервью в прошлом месяце (дополнительные ответы)

JavaScript

предисловие

 У автора два года опыта фронтенда.Был фронт-ендом около месяца.За этот период познакомился со многими компаниями,такими как有赞,涂鸦智能,滴滴,字节,酷家乐 大搜车,海康威视,税友Подождите, разберитесь с некоторыми вопросами, исходя из того, что мне задавали на личном собеседовании (包括但不限于).

   Перед началом собеседования также очень важно отличное резюме.Рекомендуются две статьи:Как должно выглядеть хорошее резюме разработчика интерфейса?,Как написать «внешнее резюме», чтобы постучать в дверь 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. Для определенных операций вы можете попробовать использовать клавиши браузера вперед и назад.image.png

Как директивы 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

Прототип + цепочка прототипов (это обязательно)

Пока проблема может быть четко описана, как объект находит свою ценность, в основном понятна половина ее.

image.pngОбъясните схему выше:

  • 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: Судя по экземпляру и конструктору, не обязательно точно, потому что он может быть переписан.

Часто используемая модель проектирования?

  • Что такое абстрактный заводской шаблон
  • В чем разница между шаблоном публикации подписки и шаблоном наблюдателя
  • Какие шаблоны проектирования вы используете в своем проекте?

рекомендуемая статья:Шаблоны проектирования, которые необходимо освоить во внешнем интерфейсе

процесс рендеринга в браузере

image.pngВ общем, я объясню процесс, опираясь на эту картинку.

Некоторые вопросы, заданные интервьюером:

  • Будет ли тег ссылки блокировать отображение страницы? Скажи мне почему?
  • Почему 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 прерывается.

image.pngРекомендуемое чтение:
Как работают браузеры: за кулисами современных веб-браузеров,

Посмотрите на процесс рендеринга в браузере и оптимизацию производительности из 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
  }
}

Как диспетчер в редуксе правильно находит редуктор?

исходный код combReducers

Да редукс его не ищет, шаттл, каждая отправка должна пройти через все редукторы...

Как 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 получается окончательное содержимое каждого модуля и зависимости между ними Выходные ресурсы: в соответствии с зависимостями между записью и модулем, сборка в Каждый фрагмент содержит несколько модулей, а затем преобразовать каждый фрагмент в отдельный файл и добавить его в список вывода.Этот шаг — последний шанс изменить содержимое вывода.
  • Вывод завершен: после определения содержимого вывода определите путь вывода и имя файла в соответствии с конфигурацией и запишите содержимое файла в файловую систему.

image.png

Как вы оптимизируете производительность веб-пакета?

рекомендуемая статья:Позвольте вам подробно разблокировать серию 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();