предисловие
фокус
Этот материал собирается отовсюду, а затем разбирается сам.Если интересы оригинального автора нарушены, если это вызывает ущемление и другие проблемы, пожалуйста, свяжитесь со мной как можно скорее! Удалите это сейчас! ! Желаю скорейшего поиска работы! ! Утка! ! Если есть какие-либо ошибки, дайте мне знать в разделе комментариев! Я изменю это! ! Ну давай же!
Первый опыт интервью маленького цыпленкаnuggets.capable/post/684490…
Тогда давайте начнем! ! ! Утка! ! !
Поскольку большинство из них также собраны из Интернета, если вы обнаружите какие-либо ошибки, пожалуйста, укажите на них в комментариях, и я их исправлю!
1. Процесс моделирования новых
Этапы реализации
- Создайте новый объект obj
- Связанный с прототипом (прототип нового объекта указывает на прототип наследуемого конструктора), obj может получить доступ к свойствам прототипа конструктора.
- Привязка this реализует наследование, и obj может получить доступ к свойствам конструктора.
- Если конструктор возвращает объект, верните его, если нет, верните obj
function Animals(name, color){
this.name = name
}
Animals.prototype.action = function () {
console.log(this.name, 'walk')
Сначала определите конструктор и его метод-прототип
Затем реализуйтеcreateспособ имитации новых
function create(constructor, ...args){
const obj = new Object()
obj.__proto__ = constructor.prototype
const res = constructor.apply(obj, args)
return res instanceof Object ? res : obj
}
Конкретное использование:
const dog = create(Animals, 'dog', 'red')
// const cat = new Animals('cat', 'yellow')
Изменение и наследование свойств путем изменения свойства [[Prototype]] объекта может иметь очень серьезное влияние на производительность, а время производительности не просто тратится в obj.proto= ..., это также влияет на все объекты, которые наследуются от этого [[Prototype]], вам не следует изменять [[Prototype]] объекта, если вы заботитесь о производительности.
Таким образом, мы можем изменить точку прототипа obj другими методами,Object.create()способ наследования
function create(constructor, ...args) {
const obj = Object.create(constructor.prototype)
const res = constructor.apply(obj, args)
return res instanceof Object ? res : obj
}
2. Функция защиты от тряски и дросселирования
Первая имитация пользовательского ввода
<div>
<input id="input"></input>
<div id="text">0</div>
</div>
Затем анти-встряска и дросселирование
// 防抖
const debounce = function (fn, delay = 1000) {
let time = null
return function (...args) {
let that = this
time && clearTimeout(time)
time = setTimeout(function () {
fn.apply(that, args)
}, delay)
}
}
// 节流
// 时间戳版
function throttle(fn, delay = 500) {
let last = 0
return function (...args) {
let now = new Date().getTime()
if (now - last > delay) {
last = now
fn.apply(this, args)
}
}
}}
// 定时器版,初次调用会延迟
const throttle = function (fn, delay = 1000) {
let time = null
return function (...args) {
let that = this
if (!time) {
time = setTimeout(function () {
time = null
fn.apply(that, args)
}, delay)
}
}
}
Тогда вы можете позвонить
const input = document.getElementById('input')
input.oninput = debounce((e) => {
document.getElementById('text').innerTexte.target.value
}, 1500)
Таким образом, могут быть реализованы функции защиты от сотрясения и дросселирования.
На самом деле здесь есть еще один более простой метод, то есть setTimeout использует стрелочные функции, так что вы можете использовать его напрямуюthis, нет необходимости генерировать дополнительную переменнуюthatЛа
const debounce = function (fn, delay = 1000) {
let time = null
return function (...args) {
time && clearTimeout(time)
time = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
3. Процесс ввода URL на дисплей
- Разбор URL, экранирование, если есть недопустимые символы
- Определите, есть ли кеш ресурса запроса
- разрешение DNS
- Трехстороннее рукопожатие TCP
- Отправить запрос, проанализировать URL, установить заголовок запроса
- Сервер возвращает запрошенный файл (html)
- рендеринг в браузере
- Разберите html файл и сгенерируйте дерево dom
- Разберите файл css и сгенерируйте дерево стилей.
- Объедините дерево домов и дерево стилей, чтобы создать дерево рендеринга (дерево рендеринга).
- рендеринг макета макета
- Страница рисования пикселей графического процессора
4. Каррирование функций
// 实现一个add方法,使计算结果能够满足如下预期:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;
В основном для сбора входящих параметров
function curry(){
const argsList = [...arguments]
const fn = function(){
argsList.push(...arguments)
return fn
}
fn.toString = function(){
return argsList.reduce((a, b) => a + b)
}
return fn
}
console.log(curry(1, 2)(3)(4, 5, 6)) // 21
Таким образом, даже если эта задача решена, вы можете свободно передавать параметры в sum, а затем превращать обычную функцию в каррированную.
function sum(a, b, c) {
return a + b + c
}
function curry(fn) {
const argsList = [...arguments].splice(1)
return function () {
const newArgsList = argsList.concat([...arguments])
if (newArgsList.length < fn.length) {
// 如果接收的参数还没有到达函数参数的个数继续收集参数
return curry.apply(this, [fn, ...newArgsList])
} else {
return fn.apply(this, newArgsList)
}
}
}
const sumAll = curry(sum)
console.log(sumAll(1)(2)(3)) // 6
console.log(sumAll(1)(2, 3)) // 6
5. Перерисовать и перекомпоновать
1. Перерисовать
Когда стиль элемента изменяется, не влияя на макет, браузер будет использовать перерисовку для обновления элемента.Поскольку в настоящее время требуется только отрисовка на уровне пользовательского интерфейса, потери невелики.
2. Оплавление
Когда размер элемента, структура или активируются определенные свойства, браузер повторно отображает страницу, это называется перекомпоновкой. В это время браузеру нужно пересчитать и переразметить страницу, поэтому потери большие
Как правило, это следующие операции:
- Первый рендер страницы
- Изменение размера окна браузера
- Размер элемента, положение, изменение содержимого
- изменение размера шрифта элемента
- Добавить или удалить видимые элементы dom
- Активировать псевдоклассы CSS, такие как
:hover - Запрашивать определенные свойства или вызывать определенные методы
- clientWidth, clientHeight, clientTop, clientLeft
- offsetWidth, offsetHeight, offsetTop, offsetLeft
- scrollWidth, scrollHeight, scrollTop, scrollLeft
- getComputedStyle()
- getBoundingClientRect()
- scrollTo()
Перерисовка должна запускать перерисовку, перерисовка не обязательно вызывает перерисовку, стоимость перерисовки мала, стоимость перекомпоновки велика
Как избежать перерисовки и возврата
CSS:
- Избегайте использования макета таблицы
- Измените класс, насколько это возможно, в конце дерева DOM.
- Избегайте использования нескольких слоев встроенных стилей.
- Применение анимационных эффектов к
position: absolute || fixedначальство - Избегайте использования выражений css (например,
calc) - Аппаратное ускорение CSS3 (ускорение GPU)
JavaScript:
- Избегайте частых манипуляций со стилями, лучше изменить атрибут стиля за один раз или определить список стилей как класс и одновременно изменить атрибут класса.
- Избегайте частых манипуляций с домом, создайте
documentFragment, примените к нему все операции с домом и, наконец, добавьте его в документ - Вы также можете сначала установить элемент
display: none, а затем отобразить его после операции, потому что операция dom для элемента, отображение которого равно none, не вызовет перерисовки и перекомпоновки - Избегайте частого чтения, это приведет к тому, что свойства перерисовки вернутся к перекомпоновке, если вам нужно использовать несколько раз, используйте переменную для приготовления
- Используйте абсолютное позиционирование для элементов со сложной анимацией, чтобы они не попадали в поток документа, иначе это приведет к частому переформатированию родительского элемента и последующих элементов.
- Используйте cssText для изменения стилей
6. Хранилище браузера
-
cookieОбычно используется для хранения информации о пользователе, статусе входа в систему и т. Д., Вы можете установить время истечения срока действия самостоятельно, а верхний предел объема составляет 4 КБ. -
localStorageНеограниченное хранилище, верхний предел объема 4~5M -
sessionStorageКогда окно браузера будет закрыто, оно будет удалено, а объем онлайн будет 4~5M.
7. Методы сетевого запроса post и get
-
getОн будет кеширован браузером, длина запроса ограничена, и он будет записан в историю.Это безвредно при откате браузера.Как правило, он отправляет TCP-пакет без тела запроса. -
postБолее безопасный, больше типов кодирования, может отправлять большие данные, когда браузер откатывается, он снова отправит запрос, обычно с телом запроса, отправив два TCP-пакета.
Когда сеть плохая, post отправляет два пакета TCP-запроса для лучшей проверки целостности.
8. Трехстороннее рукопожатие TCP
Зачем вам нужно рукопожатие TCP?
Чтобы предотвратить внезапную отправку сегмента неудачного запроса на соединение обратно на сервер, что приведет к ошибке
- Клиент отправляет запрос на синхронизацию (порядковый номер синхронизации), переходит в состояние syn_send и ожидает подтверждения.
- Сервер принимает пакет syn и подтверждает его, отправляет пакет syn+ack и входит в состояние syn_recv
- Клиент принимает пакет syn+ack, отправляет пакет ack, и обе стороны входят в установленное состояние
9. ПТС махнул четыре раза
- Клиент отправляет fin серверу, чтобы закрыть передачу данных от клиента к серверу. Клиент входит в состояние fin_wait
- После того, как сервер принимает fin, он отправляет пакет подтверждения клиенту. Сервер переходит в состояние close_wait
- Сервер отправляет fin клиенту, чтобы закрыть передачу данных от сервера к клиенту. Сервер переходит в состояние last_ack
- После того, как клиент получает фин, он переходит в состояние time_wait, затем отправляет акк на сервер, и сервер переходит в закрытое состояние.
Почему установление представляет собой трехстороннее рукопожатие, а закрытие — четырехстороннее рукопожатие?
Потому что при установлении соединения клиент принимает пакет syn+ack. Когда он закрыт, после того, как сервер принимает fin, клиент просто больше не отправляет данные, но все еще может получать данные. В это время сервер может выбрать немедленное закрытие соединения или отправку дополнительных данных, а затем отправить пакет fin, чтобы закрыть соединение. Поэтому пакеты fin и ack обычно отправляются отдельно.
10. Утечка памяти
- неожиданная глобальная переменная
- Закрытие
- Таймер не очищен
- Слушатель неразрушенных событий
- ссылка на дом
11. Характеристики наследования классов
class Dog {
constructor(name) {
this.name = name;
}
}
class Labrador extends Dog {
// 1
constructor(name, size) {
this.size = size;
}
// 2
constructor(name, size) {
this.name = name;
this.size = size;
}
// 3
constructor(name, size) {
super(name);
this.size = size;
}
};
Как и в приведенном выше коде, и 1, и 2 сообщат об ошибке.ReferenceErrorвызывает ошибку ссылки, потому что в подклассе после вызоваsuperбыл недоступен раньшеthisиз
12. Распространенные регулярные выражения
验证数字的正则表达式集
验证数字:^[0-9]*$
验证n位的数字:^\d{n}$
验证至少n位数字:^\d{n,}$
验证m-n位的数字:^\d{m,n}$
验证零和非零开头的数字:^(0|[1-9][0-9]*)$
验证有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
验证有1-3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
验证非零的正整数:^\+?[1-9][0-9]*$
验证非零的负整数:^\-[1-9][0-9]*$
验证非负整数(正整数 + 0) ^\d+$
验证非正整数(负整数 + 0) ^((-\d+)|(0+))$
验证长度为3的字符:^.{3}$
验证由26个英文字母组成的字符串:^[A-Za-z]+$
验证由26个大写英文字母组成的字符串:^[A-Z]+$
验证由26个小写英文字母组成的字符串:^[a-z]+$
验证由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
验证由数字、26个英文字母或者下划线组成的字符串:^\w+$
验证用户密码:^[a-zA-Z]\w{5,17}$ 正确格式为:以字母开头,长度在6-18之间,只能包含字符、数字和下划线。
验证是否含有 ^%&',;=?$\" 等字符:[^%&',;=?$\x22]+
验证汉字:^[\u4e00-\u9fa5],{0,}$
验证Email地址:^\w+[-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
验证InternetURL:^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ ;^[a-zA-z]+://(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$
验证电话号码:^(\d3,4\d3,4|\d{3,4}-)?\d{7,8}$:--正确格式为:XXXX-XXXXXXX,XXXX-XXXXXXXX,XXX-XXXXXXX,XXX-XXXXXXXX,XXXXXXX,XXXXXXXX。
验证身份证号(15位或18位数字):^\d{15}|\d{}18$
验证一年的12个月:^(0?[1-9]|1[0-2])$ 正确格式为:“01”-“09”和“1”“12”
验证一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$ 正确格式为:01、09和1、31。
整数:^-?\d+$
非负浮点数(正浮点数 + 0):^\d+(\.\d+)?$
正浮点数 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
非正浮点数(负浮点数 + 0) ^((-\d+(\.\d+)?)|(0+(\.0+)?))$
负浮点数 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数 ^(-?\d+)(\.\d+)?$
13. Перекрестный домен
теги link, img, script могут быть междоменными
междоменное поведение
- Те же ограничения политики происхождения, соображения безопасности (например, файлы cookie)
- Различные протоколы, IP-адреса и порты — все это междоменное поведение.
Общий перекрестный домен
- jsonp
- cors
- websocket
- postMessage + iframe
- document.domain + iframe
- window.name + iframe
- nginx-прокси
- Вложение iframe для перекрестного домена
JSONP
const script = document.createElement('script')
script.type = 'text/javascript'
script.src = 'xxx.com/login?user=xxx&password=123&callback=onBack'
document.head.appendChild(script)
function onBack(res) {
console.log(res)
}
Перекрестный домен CORS
CORS (Cross-Origin Resource Share) совместное использование ресурсов между источниками позволяет браузеру отправлять запросы XMLHttpRequest на сервер для преодоления междоменных проблем. Для этого требуется, чтобы и браузер, и сервер поддерживали
- Сторона браузера автоматически добавит в заголовок запроса
orginполе, указывающее источник текущего запроса - Сервер должен установить заголовок ответа
Access-Control-Allow-Methods,Access-Control-Allow-Headers,Access-Control-Allow-Originи другие поля, указывающие разрешенные методы, заголовки, источники и другую информацию - Запросы делятся на простые запросы и непростые запросы. Непростые запросы будут сделаны один раз в первую очередь.
OPTIONSЗапрос, чтобы определить, разрешен ли в настоящее время междоменный доступ
простой запрос
Метод запроса является одним из трех:
- HEAD
- POST
- GET
Информация заголовка HTTP-запроса не превышает следующих полей:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type (ограничено тремя значениями:
application/x-www-form-urlencoded,multipart/form-data,text/plain)
Информация заголовка ответа бэкэнда:
-
Access-Control-Allow-Orgin: Это поле обязательно, его значение либо при запросеorginЗначение , или * означает разрешение доступа с любого доменного имени -
Access-Control-Allow-Credentials: Это поле является необязательным и представляет собой логическое значение, указывающее, разрешено ли отправлятьcookies -
Access-Control-Expose-Headers: Это поле является необязательным, если вы хотите, чтобы объект XMLHttpRequestgetResponseHeader()способ получения большего количества заголовков запроса, необходимо указать в этом поле
не простой запрос
Непростые запросы относятся к запросам, которые имеют особые требования к серверу, такие как:
- Метод запроса
PUTа такжеDELETE -
Content-Typeдляapplication/json
Непростой запрос добавит запрос HTTP-запроса перед формальным общением, называемым предварительным запросом, которыйoptionsЛа
-
Access-Control-Request-Methor: это поле необходимо, чтобы указать, какие методы HTTP будут использоваться в запросе CORS браузера, напримерPUT -
Access-Control-Request-Headers: это поле представляет собой строку, разделенную запятыми, которая указывает дополнительную информацию заголовка запроса, которую будут отправлять запросы CORS браузера.
CORS против JSONP
- JSONP можно использовать только для
GETзапросы, CORS поддерживает все типы HTTP-запросов - Преимущество JSONP в том, что он поддерживает старые браузеры и может отправлять запросы на веб-сайты, которые не поддерживают CORS.
14. Кэш
На самом деле, он обычно разрабатывается и используется
webpackПри построении суффикс имеет хеш-значение, которое на самом деле связано с кэшированием.
Кэши можно разделить на сильные кеши и согласованные кеши. Надежный кеш не может использоваться сервером, а согласованный кеш должен быть пропущен через сервер. Код состояния, возвращаемый кэшем согласования, — 304. Одновременно могут существовать два типа кешей, и приоритет надежного кеша выше, чем у согласованного кеша. При выполнении сильного кэширования, если кеш попадает, данные в базе данных кеша используются напрямую, а согласованный кеш не выполняется.
Сильный кеш
Expires (HTTP 1.0):ExpiresЗначение представляет собой время истечения срока действия данных, возвращаемых сервером. Когда время повторного запроса меньше времени истечения срока действия, кэшированные данные используются напрямую. Однако из-за разницы во времени между сервером и клиентом может возникнуть ошибка попадания в кэш. Также чаще всего используютCache-Controlзаменять
Pragma (HTTP 1.0): Поле, оставшееся от HTTP 1.0, когда значение равноno-cacheКогда кеш принудительно проверяется, Pragma отключает кеш, если он задан.ExpiresОпределите неистекшее время, тогда прагма будет иметь более высокий приоритет. Добавлен ответ сервераPragma: no-cache, браузер ведет себя как обновление (F5)
Cache-Control (HTTP 1.1): имеет следующие свойства
- частный: клиент может кэшировать
- Публичный: Клиент и прокси-сервер могут кэшировать
- max-age=t: кешированный контент истечет через t секунд
- no-cache: для проверки кэшированных данных требуется согласование кеша.
- no-store: весь контент не будет кэшироваться
No-cache не означает отсутствие кэширования, no-cache означает, что его можно кэшировать, но каждый раз сервер должен проверять, доступен ли кэш. no-store — не кэшировать контент.
Когда заголовок ответаCache-Controlуказанныйmax-age, приоритет будет выше, чемexpiresвысоко.
Форма обращения к сильному кешу: браузер Firefox: серый код состояния 200, браузер Chrome: 200 (из кеша диска) или 200 OK (из кеша памяти)
Согласовать кеш
Согласование кеша требует сравнения, чтобы определить, можно ли использовать кеш. Когда браузер запрашивает данные в первый раз, сервер ответит клиенту идентификатором кеша и данными, и клиент создаст их резервную копию в кеше. При повторном запросе клиент отправит идентификатор в кеше на сервер, и сервер будет судить на основе этого представления. Если он не является недействительным, возвращается код состояния 304, и браузер может использовать кэшированные данные сразу после получения этого кода состояния.
Last-Modified: Когда сервер снова ответит на запрос, он сообщит браузеру время последней модификации ресурса, потому что он может быть изменен несколько раз за последнюю секунду, или время сервера и клиента может быть разным, что может привести к кешированию. пропустить, поэтому он был запущен позже.etag
if-Modified-Since: когда браузер снова запрашивает сервер, заголовок запроса будет содержать это поле, за которым следует время последней модификации, полученное в кеше. Сервер получает этот запрос и обнаруживает, чтоif-Modified-SinceПосле сравнения времени последней модификации запрошенного ресурса, если возвращается ответ 304, браузеру нужно только получить данные из кеша.
- Если ресурс изменен, сервер передает все данные и возвращает 200 OK.
- Если он не был изменен, серверу нужно только передать информацию заголовка ответа, и сервер возвращает 304 Not Modified.
if-Unmodified-Since: с определенного момента времени, независимо от того, был ли файл изменен, используется относительное время, и нет необходимости заботиться о разнице во времени между клиентом и сервером.
- Если он не был изменен, он продолжит передачу данных, и сервер вернет 200 OK.
- Если файл был изменен, он не будет передан, и сервер вернет 412 Precondition failed (ошибка предварительной обработки)
Разница между ними в том, что один загружается только после модификации, а другой загружается без модификации.
Если на сервере ресурс модифицировался, но его фактическое содержимое не изменилось, т.к. Last-Modified time match не идет на возврат всех данных клиенту (даже если в клиентском кеше ресурсы одинаковые) для того чтобы решить эту проблему, нам нужно использовать HTTP 1.1Etag
Etag: Когда сервер отвечает на запрос, это поле сообщает браузеру уникальный идентификатор текущего ресурса, сгенерированный сервером (правило генерации определяется сервером)
If-Match: Условный запрос, несущий ресурс в предыдущем запросеEtag, по этому полю сервер судит, есть ли у файла новая модификация
If-None-Match: При повторном запросе к серверу заголовок сообщения запроса браузера будет содержать это поле, а следующее значение - идентификатор, полученный в кеше.После получения сообщения сервер находит, чтоIf-None-Matchсравнивается с уникальным представлением запрошенного ресурса
- Если он отличается, это означает, что ресурс был изменен, и возвращается код состояния 200, соответствующий всему содержимому ресурса.
- То же, указывая на то, что ресурс не был изменен, заголовок ответа, браузер напрямую получает информацию о данных из кеша, а сервер возвращает код состояния 304
Точность Etag выше, чем Last-modified, который относится к строгой проверке, требует постоянного уровня байтов ресурсов и высокого приоритета. Если ETag предоставляется сервером, сначала необходимо выполнить условный запрос для ETag.
Однако в практических приложениях из-за
EtagРасчет получается по алгоритму, а алгоритм будет занимать ресурсы серверных вычислений.Все серверные ресурсы драгоценны, поэтому редко используются.Etagохватывать
- Браузер вводит URL-адрес, и после нажатия Enter браузер обнаруживает, что файл уже существует в кеше, поэтому нет необходимости продолжать запрос, а информация о данных берется напрямую из кеша
- Обновление F5 означает, что браузер отправляет запрос на сервер, содержащий
If-Modified-Sinceчтобы узнать, не истек ли срок действия файла - Ctrl+F5 принудительное обновление, то есть сначала удалить файл в кеше, а потом перейти к серверу для запроса полного ресурса, таким образом, клиент завершил операцию принудительного обновления
Сцена кэша
В большинстве случаев сильное кэширование можно использовать в сочетании с согласованным кэшированием, но в некоторых особых случаях может потребоваться выбор специальной стратегии кэширования.
- Для некоторых ресурсов, которые не нужно кэшировать, вы можете использовать
Cache=Control: no-storeчтобы указать, что ресурс не нужно кэшировать - Для часто меняющихся ресурсов можно использовать
Cache-Control: no-cacheи сотрудничатьEtagИспользуется, указывая, что ресурс кэшируется, но каждый раз, когда отправляется запрос, чтобы узнать, обновлен ли ресурс - Для файлов кода обычно используют
Cache-Control: max-age=31536000И используйте его с кешем политики, а затем отпечатайте файл.Как только имя файла изменится, новый файл будет загружен немедленно.
15. Рукописный вызов, применение, связывание
Function.prototype.myCall = function (obj = window) {
obj.fn = this
const args = [...arguments].splice(1)
const result = obj.fn(...args)
delete obj.fn
return result
}
Function.prototype.myApply = function (obj = window) {
obj.fn = this
const args = arguments[1]
let result = args ?
obj.fn(...args) :
obj.fn()
delete obj.fn
return result
}
Function.prototype.myBind = function (obj = window) {
const that = this
const args = [...arguments].splice(1)
return function () {
return that.apply(obj, [...args, ...arguments])
}
}
// 然后使用即可
function log() {
console.log(this)
console.log(this.value)
console.log(arguments)
}
const obj = {
value: 123
}
log.myCall(obj, 1, 2, 3)
log.myApply(obj, [1, 2, 3])
log.myApply(obj)
log.myBind(obj)()
log.myBind(obj)(1, 2, 3)
log.myBind(obj, 4, 5, 6)(1, 2, 3)
16. Разница между псевдоклассами и псевдоэлементами
Псевдоклассы и псевдоэлементы используются для украшения частей, которых нет в дереве документа, таких как первая буква предложения или первый элемент в списке.
псевдокласс
Псевдоклассы используются для добавления соответствующих стилей к существующим элементам, когда они находятся в определенном состоянии, которое меняется в зависимости от поведения пользователя. Например зависнуть. Хотя он похож на обычный CSS, он может добавлять стили к существующим элементам, но может добавлять стили к элементам только тогда, когда он находится в состоянии, которое не может быть описано деревом dom.Так называемый псевдокласс
псевдоэлемент
Псевдоэлементы используются для создания и оформления элементов, которых изначально нет в дереве документа, таких как:before. Хотя пользователь может видеть это содержимое, на самом деле он не находится в дереве документа.
разница
Псевдо-классы работают на элементах, которые уже существуют в дереве документа, а псевдоэлементы создают элемент за пределами дерева документа. Следовательно, разница между псевдоклассами и псевдоэлементами заключается в следующем:Нет внешних элементов для создания дерева документов
Используйте два двойных двоеточия в спецификации css::для представления псевдоэлементов двоеточие:представлять псевдоклассы. Например:::before,:hover
17. Абсолютное позиционирование
- Если родительский элемент является элементом уровня блока, дочерний элемент устанавливается на границу заполнения родительского элемента.
- Если родительский элемент является встроенным элементом, дочерний элемент устанавливается на границе содержимого родительского элемента.
Прикрепите каскадную контекстную таблицу
18. Разница между window.onload и doument.onload
- window.onload: относится к триггеру, когда все dom, таблицы стилей, скрипты, изображения и флэш-память на странице загружены.
- document.onload: относится к завершению загрузки dom, исключая другие вещи.
19. Делегация мероприятия
Делегирование события заключается в делегировании функции времени отклика одного элемента (щелчок, нажатие клавиши....) другому элементу. Как правило, время элемента или группы элементов делегируется родительскому или внешнему элементу. Это внешний элемент, который на самом деле связывает событие. Когда событие отвечает на элемент, который необходимо связать, оно будет использовать механизм всплытия событий, чтобы инициировать событие связывания своего внешнего элемента, а затем выполнить внешнюю функцию.
- Подобно KeyDown, доверены события мыши onclick, события клавиатуры, поддержка всплывающих событий.
- Подобные события интерфейса: изменение, отправка не имеет прокси события
всплывающее окно события
Модель событий делится на три этапа
- Фаза захвата: в модели с всплывающей диаграммой событий фаза захвата не реагирует ни на какие события.
- Целевой этап: Целевой этап относится к реакции события на самый нижний элемент, который запускает событие.
- Стадия всплытия: Этап всплытия заключается в том, что триггерный ответ события будет переходить от нижней цели к самому внешнему элементу (корневому узлу) слой за слоем.
Преимущества делегирования мероприятия
- Уменьшить потребление памяти
Предположим, что есть список, есть много Li, если вы связываете событие для каждого из них, он тратит память, лучше всего привязать к нашему времени на внешний слой.
ulединая обработка
<ul id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
......
<li>item n</li>
</ul>
// ...... 代表中间还有未知数个 li
Таким образом, делегирование событий может значительно снизить потребление памяти и повысить эффективность.
- Динамически связывать события Если нам нужно динамически добавлять и удалять элементы в списке, то мы должны перепривязывать событие каждый раз, когда оно изменяется. Если вы используете делегирование события, такой проблемы нет, потому что событие привязано к родительскому элементу и не имеет ничего общего с добавлением или удалением целевого элемента.
Таким образом, делегирование событий может динамически связывать время, сокращая объем повторяющейся работы.
window.onload = () => {
const list = document.getElementById('list')
list.addEventListener('click', function (event) {
console.log(event.target)
})
}
<ul class="list" id="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
Таким образом, время щелчка по метке li поднимется до ul, а затем будет выполнен метод привязки.
Уведомление
Анализ ситуации:
- Если вы получите узел, вы сначала захватите его, а если нет, он всплывет, чтобы найти его.
- Если через node.addEventListener('event',обратный вызов,пузырь или захват); тот, кто вызовет первым, будет выполняться первым
20. Принцип реализации instanceof
while (x.__proto__) {
if (x.__proto__ === y.prototype) {
return true
}
x.__proto__ = x.__proto__.__proto__
}
if(x.__proto__ === null){
return false
}
Чтобы определить, является ли объект x экземпляром y, он всегда будет искать в цепочке прототипов и возвращать true, если он будет найден.
21. Наследование
- прототипное наследование
Student.prototype = new Person('b')
Student.prototype.constructor = Student
недостаток:
- Подтипы не могут передавать аргументы супертипам
- Методы подкласса должны быть написаны на
new Personназад, иначе он будет перезаписан
- наследование классов
function Child(name, parentName) {
Parent.call(this, parentName);
this.name = name;
}
недостаток:
- Прототипа нет, каждое творение будет выполнять parent.call
- наследование композиции
function Child(name, parentName) {
Parent.call(this, parentName);
this.name = name;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
недостаток:
- Конструктор родительского класса будет вызываться дважды
- паразитарное сочетание
function Person(name) {
this.name = name
}
Person.prototype.a = function () {
console.log('person a')
}
Person.prototype.b = function () {
console.log('person b')
}
function Student(name, superName) {
Person.call(this, superName)
this.name = name
}
Student.prototype = Object.create(Person.prototype)
Student.prototype.constructor = Student
Student.prototype.b = function () {
console.log('student b')
}
const person = new Person('p')
const student = new Student('s')
console.log(person)
console.log(student)
person.a()
person.b()
student.a()
student.b()
console.log(student instanceof Person)
22. для...в и для...из
- для ... в for...in перебирает все свойства проходимого объекта
const arr = [5, 4, 3, 2, 1]
arr.name = 'name'
for(let i in arr){
console.log(i) // 0 1 2 3 4 name(字符串类型的索引)
}
вывод0 1 2 3 4 name, потому что мы даем Arr добавлен атрибут Name, для... я буду проходить по нему.
Итак, for...in обычно используется для обхода объектов, а значение является его ключевым значением.
- for...of
const arr = [5, 4, 3, 2, 1]
arr.name = 'name'
for(let i in arr){
console.log(i) // 0 1 2 3 4 name(字符串类型的索引)
}
вывод5 4 3 2 1, введите значение каждого в массив
Суммировать
- for...of имеет объекты-итераторы, использующие обходные массивы/объекты-массивы/строки/карту/набор и т. д., но не может проходить объекты, поскольку объекты не имеют объектов-итераторов. Он может использовать break, continue, return
- for...in для перебора объектов или использования
Object.keys() - for...in проходит по индексу (имя ключа) массива, а for...of является значением массива
23. Сглаживание массива
const test = [
[1, 2, 2],
[3, 4, 5, 5],
[6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10
]
// 要求将以上数组扁平化排序且去重
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
// 递归版
function flat(arr) {
let list = []
arr.forEach(item => {
if (Array.isArray(item)) {
list.push(...flat(item))
// list = list.concat(flat(item))
} else {
list.push(item)
}
})
return list
}
const res1 = [...new Set(flat(test))].sort((a, b) => a - b)
// ES6版
const res2 = [...new Set(test.flat(Infinity))].sort((a, b) => a - b)
console.log(res1)
console.log(res2)
24. Оптимизация производительности интерфейса
когда пишешь
-
Обратите внимание на утечки памяти при написании кода (таймеры, прослушиватели событий, замыкания, глобальные переменные, ссылки на dom и т. д.)
-
В части css не используйте компоновку таблиц, выражения css и т. д., которые вызовут перекомпоновку, и можно включить аппаратное 3D-ускорение (перспектива, мерцание исправлений обратной видимости)
-
js, не меняйте часто стиль, операцию dom, вы можете использовать скрипт дросселирования против сотрясений в нижней части страницы.
-
Часть WebPack может сжать JS, CSS, общие ресурсы, такие отдельные библиотеки пользовательских интерфейсов компонентов, компонент конфигурации, загруженные по требованию (импорт ()).
-
Часть браузера может установить кеш, использовать cdn
-
Картинки можно сжимать, используя формат webp, спрайтовые картинки и т.д. Когда картинок много, можно использовать ленивую загрузку и другие методы
-
В части React вы можете использовать shouldComponentUpdate, React.Memo, pureComponent, элементы списка для установки ключей и пытаться связать функции в конструкторе и т.д.
-
Nginx может настроить балансировку нагрузки, а несколько серверов могут использовать Redis для поддержания сеансов.
-
содержание страницы
- Уменьшите количество HTTP-запросов
- Уменьшить DNS-запросы
- Избегайте перенаправлений
- Кэшировать Ajax-запросы
- ленивая загрузка
- предварительная загрузка
- уменьшить количество элементов dom
- Разделите различный контент на разные домены
- Сведите к минимуму использование iframe
- Избегайте ошибок 404
-
сервер
- Используйте CDN
- Добавьте заголовки ответа Expires или Cache-Control
- Gzip включен
- Настроить Etags
- ранняя буферизация вывода
- Ajax-запрос с использованием метода get
- Избегайте того, чтобы src изображения был пустым
-
Cookie
- Уменьшить размер файла cookie
- Используйте домены без файлов cookie для статических ресурсов
-
Css
- поместите таблицу стилей в
<head>середина - Не используйте выражения CSS
- использовать
<linkзаменять@import - не использовать фильтр
- поместите таблицу стилей в
-
JavaScript
- Поместите скрипт внизу страницы
- Используйте внешний JavaScript и CSS
- Сжимайте JavaScript и CSS
- Избегайте дублирования сценариев
- Сокращение операций с домом
- Используйте эффективную обработку времени
-
картина
- Оптимизация изображений
- Оптимизация спрайтов CSS
- Не масштабировать изображения в HTML
- Используйте небольшой кешируемый файл favicon.ico
-
мобильный
- Размер отдельных файлов должен быть меньше 25 КБ.
- Упаковать содержимое как составной документ
25. js для достижения анимации
Плавно перемещайте div, от быстрого к медленному, не можете использовать свойства css3
<!DOCTYPE html>
<html>
<head>
<script>
window.onload = () => {
var element = document.getElementById('t');
function step(timestamp) {
console.log(timestamp)
var progress = timestamp;
// element.style.left = (progress / 30) * (10 - progress / 1000) + 'px';
element.style.left = Math.pow(progress / 5, .5) * 40 + 'px';
if (progress < 5000) {
window.requestAnimationFrame(step);
} else {
window.cancelAnimationFrame(step)
}
}
window.requestAnimationFrame(step);
}
</script>
<style>
.container {
position: relative;
width: 1000px;
}
#t {
position: absolute;
width: 50px;
height: 50px;
background: red;
}
</style>
</head>
<body>
<div class="container">
<div id="t"></div>
</div>
</body>
</html>
26. Реализуйте атрибут автозаполнения
Существует поле ввода ввода, при вводе ключевых слов имитируйте эффект автозаполнения для завершения
<!DOCTYPE html>
<html>
<head>
<script>
window.onload = () => {
const input = document.getElementById('input')
const words = ['珠海', '广州', '上海', '杭州', '成都']
input.addEventListener("input", debounce(function (e) {
const value = e.target.value
const index = words.findIndex((item) => value && item.indexOf(value) !== -1)
if (index !== -1) {
e.target.value = words[index]
}
}, 500))
function debounce(fn, wait = 500) {
let timeout = null
return function () {
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(() => {
fn.apply(this, [...arguments])
}, wait)
}
}
}
</script>
<style>
</style>
</head>
<body>
<input id="input" />
</body>
</html>
27. Глубокая копия реализации кода
const deepClone = (obj) => {
let result = null
if (typeof obj === 'object') {
result = Array.isArray(obj) ? [] : {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === 'object') {
result[key] = deepClone(obj[key])
} else {
result[key] = obj[key]
}
}
}
} else {
// 如果不是对象与数组,则直接赋值
result = obj
}
return result
}
Или используйте свой собственный метод
JSON.parse(JSON.stringify(obj))
28. Нестандартный алгоритм
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Простая версия
arr.sort(() => Math.random() - 0.5)
Алгоритм перемешивания
const shuffle = (arr) => {
let len = arr.length
while (len > 1) {
let index = Math.floor(Math.random() * len--);
[arr[index], arr[len]] = [arr[len], arr[index]]
}
return arr
}
29. Дедупликация массива
const arr = [1, 1, 1, 2, 3, 4, 5, 5, 3, 2, 1, 1]Простая версия
[...new Set(arr)]
Версия для петли
const removeDrop = function () {
const result = []
const map = {}
arr.forEach((item) => {
if (!map[item]) {
map[item] = true
result.push(item)
}
})
return result
}
30. Роль ключей в React
Обзор
Ключи используются, чтобы помочь React определить, что было изменено, добавлено или удалено. Значение ключа должно быть стабильным, потому что, если ключ изменится, реакция вызовет повторную визуализацию пользовательского интерфейса.
-
Уникальность: значение ключа должно быть уникальным. Если встречается такое же значение, будет выдано предупреждение, и будет отображаться только первый элемент с повторяющимся значением ключа. Потому что react будет думать, что последующие компоненты с одинаковым значением ключа являются одним и тем же компонентом.
-
Нечитаемо: несмотря на то, что ключ определен в компоненте, значение ключа не может быть получено в подкомпоненте.
Если вы измените ключевое значение компонента, вы можете уничтожить предыдущий компонент и создать новый компонент
Уведомление
Если это связано с динамическими изменениями в массиве, такими как добавление элементов в массив, удаление и перестановка, если индекс используется в качестве значения ключа в это время, это приведет к отображению неверных данных.
{this.state.data.map((v,idx)=><Item key={idx} v={v} />)}
// 开始时:['a','b','c']=>
<ul>
<li key="0">a <input type="text"/></li>
<li key="1">b <input type="text"/></li>
<li key="2">c <input type="text"/></li>
</ul>
// 数组重排 -> ['c','b','a'] =>
<ul>
<li key="0">c <input type="text"/></li>
<li key="1">b <input type="text"/></li>
<li key="2">a <input type="text"/></li>
</ul>
Если ключ тот же, а компонент меняется, будут обновлены только измененные свойства, если ключ другой, предыдущий компонент будет уничтожен, а весь компонент будет перерендерен.
Сценарии, использующие индекс в качестве ключа
第一页
<ul>
<li key="0">张三</li>
<li key="1">李四</li>
<li key="2">王五</li>
</ul>
第二页
<ul>
<li key="0">张三三</li>
<li key="1">李四四</li>
<li key="2">王五五</li>
</ul>
После перелистывания страницы значение подкомпонента меняется, но ключ остается прежним, только обновление будет происходить, а перерисовываться не будет
антишаблон
Теперь есть пример, если мы не добавим ключ, реакция будет автоматически использовать индекс в качестве значения ключа.
let arr = ['first', 'second'];
// list1 和 list2 是等价的
const list1 = arr.map(item => <p>{item}</p>);
const list2 = arr.map((item, index) => <p key={index}>{item}</p>);
Затем мы добавляем элемент в конец массива.После того, как реакция проходит алгоритм diff, элементы со значениями ключа 0 и 1 не изменились, поэтому операция над UI заключается только в том, чтобы добавить еще один элемент в конец конец.
Но если вы добавите элемент в начале
<!-- before -->
<p key="0">first</p>
<p key="1">second</p>
<!-- after -->
<p key="0">zero</p>
<p key="1">first</p>
<p key="2">second</p>
Поэтому ключевое значение элемента изменилось, так что каждый элемент будет перерисован один раз, и это сильно повлияет на производительность.
Суммировать
Короче говоря, изменение значения ключа для повторного рендеринга компонента — это очень недорогой способ по сравнению со сложным жизненным циклом componentWillReceiveProps.
31. Реагировать на серию
Когда вызывается функция рендеринга компонента
Каждое государственные изменения сделают функцию рендеринга, но не обязательно произойдет изменение страницы DOM
жизненный цикл компонента
- Этап инициализации (монтаж)
- Обновление
- Фаза разрушения (размонтирование)
Этап инициализации:
- конструктор(): используется для привязки событий и инициализации состояния
- componentWillMount(): компонент будет монтироваться, вызываться перед рендерингом, и каждый компонент вызывается перед рендерингом, обычно здесь рабочее состояние. можно вызвать на сервер
- render(): используется для рендеринга dom
- componentDidMount(): вызывается после рендеринга и после рендеринга всех подкомпонентов, обычно используется для асинхронного запроса данных, поскольку здесь инициализируются компоненты
Этап обновления:
- componentWillReceiveProps(nextProps): здесь вы можете получить состояние, которое должно измениться, вы можете установить состояние с помощью метода setState здесь
- shouldComponentUpdate(nextProps, nextState): возвращаемое значение определяет, будет ли вызван следующий цикл объявления, и по умолчанию возвращает true.
- componentWillUpdate(): Здесь нельзя изменить состояние, иначе оно попадет в бесконечный цикл
- componentDidUpdate(): аналогично componentDidMount(), здесь выполняются операции Dom и инициируются сетевые запросы.
Фаза разрушения
- componentWillUnmount(): в основном выполняет работу по очистке, такую как отмена сетевых запросов и очистка прослушивателей событий.
Virtual Dom
Трудность заключается в том, как отличить старый объект от нового.
Метод реакции состоит в том, чтобы сравнивать только узлы одного и того же уровня, а не межуровневое сравнение.
Шаги делятся на два шага:
- Во-первых, обход объекта сверху вниз и слева направо, то есть обход дерева в глубину, Этот шаг добавит индекс к каждому узлу, чтобы облегчить окончательный рендеринг разницы.
- Когда у узла есть дочерние элементы, проверьте, отличаются ли дочерние элементы.
Реализация алгоритма Virtual Dom в основном состоит из трех шагов.
- Имитация создания объектов dom через js
- Преобразуйте виртуальный дом в настоящий дом и вставьте его на страницу
- Когда есть изменение, сравните различия между двумя деревьями и сгенерируйте объект различия.
- Рендеринг diff в реальный дом на основе объекта diff
Синхронизация setState? асинхронный?
- setState есть только в синтетических событиях (onClick, onChange и т. д. в JSX) и функциях ловушекасинхронныйДа, как в нативных событиях, так и в setTimeout синхронно
- «Асинхронность» setState не означает, что внутренность реализована асинхронным кодом, на самом деле процесс и код, исполняемый сам по себе, синхронны, но последовательность вызова синтетического события и функции-ловушки предшествует обновлению, что приводит к сбою синтетического события и функции хука.Метод сразу получает обновленное значение, конечно, его можно получить и вторым параметром setState
- Оптимизация пакетного обновления setState основана на «асинхронности» (синтетические события, функции-ловушки). В исходном времени и setTimeout пакетные обновления не будут выполняться. В «асинхронном режиме», если значение setState несколько раз, стратегия пакетного обновления setState перезапишет его, и будет выполнено последнее выполнение. Значение, которое будет объединяются при пакетном обновлении
class App extends React.Component {
state = { val: 0 }
componentDidMount() {
this.setState({ val: this.state.val + 1 })
console.log(this.state.val)
this.setState({ val: this.state.val + 1 })
console.log(this.state.val)
setTimeout(_ => {
this.setState({ val: this.state.val + 1 })
console.log(this.state.val);
this.setState({ val: this.state.val + 1 })
console.log(this.state.val)
}, 0)
}
render() {
return <div>{this.state.val}</div>
}
}
Поскольку setState является асинхронным в функции ловушки, значение val не может быть получено в первые два раза, поэтому выводится 0. Затем, когда достигается setTimeout, setState обновляется, и, поскольку это пакетное обновление, только в последний раз выполняется, поэтому setTimeout , val равно 1. Поскольку setTimeout является синхронным, первый раз равен 2, а второй раз — 3.
32. Реагируйте на распространенные вопросы интервью
Что происходит после вызова setState
После того, как код вызовет функцию setState, React объединит входящий объект параметра с текущим состоянием компонента, а затем запустит процесс настройки.После процесса настройки Recon относительно эффективно построит дерево элементов React в соответствии с новое состояние и рендеринг всего пользовательского интерфейса. После того, как React получит дерево элементов, будет рассчитана разница узлов между новым деревом и старым деревом, а затем рендеринг интерфейса будет минимизирован в соответствии с разницей. В дифференциальном алгоритме React может относительно точно знать, что эти места изменились, что гарантирует их обновление по требованию, а не весь рендеринг.
Разница между элементом и компонентом в React
React Element — это структура данных, описывающая то, что видно на экране, и представляющая собой объектное представление пользовательского интерфейса. Компонент React — это функция или класс, который может принимать ввод параметров и возвращать элемент React.
При каких обстоятельствах вы бы предпочли использовать компонент класса вместо функционального компонента
Выберите компонент класса, если компоненту требуются функции внутреннего состояния и жизненного цикла, в противном случае используйте функциональный компонент.
Какова роль рефов в React
Refs - это ручка, предоставляемая реагированием, которая может безопасно получить доступ к элементу DOM или экземпляра компонента. Вы можете добавить атрибут REF в элемент, а затем принять диск элемента в дереве DOM в функции обратного вызова
Роль ключей в реакции
Ключи — это вспомогательные идентификаторы, которые React использует для отслеживания того, какие элементы в списке были изменены, добавлены или удалены, это необходимо для обеспечения уникальности ключей. В алгоритме React diff значение ключа используется для определения того, был ли элемент создан заново или перемещен, тем самым уменьшая ненужную повторную визуализацию элемента. Кроме того, React также необходимо использовать значение ключа для определения связи между элементом и состоянием.
Разница между контролируемыми и неконтролируемыми компонентами
- Управляемые компоненты относятся к тем компонентам, которые единообразно управляют данными формы для React и должны использовать setState для обновления значения формы.
this.state = {
value: ''
}
...
handleChange = (e) => {
this.setState({
value: e.target.value
})
}
...
<input onChange={() => this.handleChange} />
- Неконтролируемые компоненты хранятся в dom для хранения данных формы, мы можем использовать refs для управления элементами dom.
handleChange = () => {
console.log(this.input.value)
}
...
<input refs={(input) => this.input = input}
onChange={() => this.handleChange} />
Хотя неконтролируемые компоненты проще реализовать, но нам иногда нужно обрабатывать данные, проще использовать контролируемые компоненты
Где в цикле объявления должен быть сделан запрос Ajax
должны быть размещеныcomponentDidMount()
- Алгоритм согласования Fiber повлияет на количество срабатываний compnentWillMount, если его разместить в нем, то он может инициировать несколько Ajax-запросов.
- Если его поместить в другие жизненные циклы, предполагая, что мы получим результат Ajax-запроса и добавим его в состояние компонента, размонтированный компонент сообщит об ошибке. пока в
componentDidMountНе будет таких проблем
Какова роль shouldComponentUpdate и почему это так важно
shouldComponentUpdate позволяет нам вручную определить, обновляется ли компонент, чтобы избежать ненужного рендеринга обновлений.
Логика обработки событий в React
Чтобы решить проблему совместимости между браузерами, React будет инкапсулировать нативные события браузера как синтетические события и передавать их в установленные обработчики событий. Синтетические события используют тот же интерфейс, что и собственное время, но они скрывают детали базовых различий браузеров и обеспечивают согласованное поведение. Вместо того, чтобы прикреплять события к дочерним элементам, React отправляет все события на верхний уровень.documentобрабатывать
Все события в JSX привязаны кdocument, не только снижает потребление памяти, но и равномерно удаляет события при уничтожении компонентов
Если мы не хотим, чтобы событие всплыло, мы должны вызватьevent.preventDefault, вместо традиционногоevent.stopPropagation
В чем разница между createElement и cloneElement
Функция createElement — это функция, используемая для создания элемента после компиляции JSX, а cloneElement — для копирования элемента и передачи новых реквизитов.
Какова роль второго параметра функции setState
Это функция обратного вызова. Эта функция будет вызываться, когда вызывается функция setState и компонент начинает повторную визуализацию. Мы можем использовать эту функцию, чтобы определить, завершена ли визуализация обновления.
Почему виртуальный дом повышает производительность
Виртуальный дом эквивалентен добавлению кеша между js и реальным домом, используя алгоритм dom diff, чтобы избежать ненужных операций с домом, тем самым повышая производительность. Конкретные шаги заключаются в следующем:
- Используйте js для имитации создания дома
- Превратите этот виртуальный дом в настоящий дом и вставьте его на страницу.
- Когда состояние изменяется, сравните различия между двумя деревьями объектов и сгенерируйте разностный объект.
- Обновление на основе объекта diff
алгоритм сравнения
- Разложите древовидную структуру по уровню, сравнивайте только элементы одного уровня
- Добавьте уникальный ключевой атрибут к каждому элементу структуры списка для удобства сравнения
- Если это компонент того же типа, он проходит в соответствии с DEAL Diff
- Если не тот же класс, компонент определяет, что грязное компонент, заменяя все дочерние узлы во всем компонентах, не нужно тратить сравнительную разницу.
- Операция слияния при вызове setState помечает компонент как грязный, а в конце цикла обработки событий React проверяет все компоненты, помеченные как грязные, на перерисовку. Таким образом, дом будет обновлен только один раз, что сэкономит производительность.
- Выборочный рендеринг поддерева с использованием shouldComponentUpdate для улучшения производительности diff
Три стратегии оптимизации алгоритма diff
- стратегия оптимизации дерева
- Иерархический контроль, один и тот же уровень дерева различий сравнивает только узлы одного уровня
- Если узел не существует, он удаляется напрямую.
- Сравнение поперечного уровня создаст или удаляет соответственно
- Стратегия оптимизации компонентов
- Это тот же тип, если да, используйте дерево diff
- Если они не одного типа, они оцениваются как грязные компоненты. Тем самым заменяя дочерние узлы под всем компонентом
- Для компонентов того же типа вы можете использовать shouldComponentUpdate для ручного завершения алгоритма diff для ускорения рендеринга.
- стратегия оптимизации элементов
- Вставить, новый узел должен выполнить операцию вставки.
- Переместить, сам узел существует и его нужно переместить
- Удалить, одна и та же структура имеет другое содержимое, не нужно повторно использовать напрямую, нужно удалить и перестроить
- Расчет на основе уникального ключа тега, быстрое позиционирование
Реагировать на оптимизацию производительности
- Используйте shouldComponentUpdate, чтобы избежать ненужных операций с домом
- Используйте ключи, чтобы помочь React определить минимальные изменения для списка подкомпонентов.
- React.memo
- SSR
- Не используйте стрелку внутри функции рендеринга или привязки, должен быть реконструктор в привязке
Ямы реакции
- componentWillUnmounted
- this.setState не синхронизирован
- pureComponent не обновляется, если prop является многоуровневым объектом
Кратко опишите идею Flux
Самая большая особенность Flux заключается в том,Односторонний поток данных
- Доступ пользователей Просмотр
- Просмотр проблем Действия пользователя
- Диспетчер получает действие и просит магазин обновить его соответствующим образом.
- После обновления Store создайте событие «change»
- После того, как View получит событие «change», обновите страницу
- Использование debounce требует сохранения ссылок на события
event.persist()
В чем разница между презентационным компонентом и компонентом-контейнером
- Компонент презентации заботится о том, как выглядит компонент, он получает данные и обратные вызовы через пропсы и, как правило, не имеет собственного состояния.
- Компоненты-контейнеры заботятся о том, как работают компоненты. Компоненты-контейнеры предоставляют данные и поведение для компонентов отображения или других компонентов-контейнеров. Обычно они имеют собственное состояние, поскольку являются источником данных для других компонентов.
В чем разница между состоянием и реквизитами компонента
- state — это структура данных, которая используется для значений данных по умолчанию, необходимых при монтировании компонента. Как правило, состояние изменяется поведением пользовательского события.
- Props — это конфигурация компонента, которая передается от родительского компонента к дочернему компоненту, и props нельзя изменить.
Что такое компоненты высшего порядка
Компонент более высокого порядка — это функция, которая принимает компонент и возвращает новый компонент. HOC запускает код повторного использования, логику и абстракции начальной загрузки. Наиболее распространенной является функция подключения Redux. Лучший способ HOC — разделить поведение между компонентами. Если вы найдете место, где много кода используется для выполнения одной задачи, вы можете подумать о рефакторинге в HOC.
Почему предлагается, чтобы параметр setState был обратным вызовом вместо объекта
Поскольку обновления состояния и свойств могут быть асинхронными, на них нельзя полагаться при вычислении следующего состояния.
Есть ли другой способ, кроме привязки этого в конструкторе?
Стрелочные функции можно использовать в обратных вызовах, но проблема в том, что каждый рендер создает новый обратный вызов.
Зачем вызывать super в конструкторе
потому чтоsuper()Подклассы не могут использовать это до вызова
Три способа сборки компонентов в React
React.createClass, класс ES6, без функции состояния
Разница между useEffect и useLayoutEffect
разное время звонка
- useEffect выполняется после рендеринга компонента
- useLayoutEffect выполняется до рендеринга компонента
useLayoutEffect выполняется перед useEffect
Реализовать useState и useEffect
React использует форму, похожую на односвязный список, вместо массива, и объединяет все хуки по порядку до следующего.
Возможности useEffect:
- Два параметра: callback-функция, массив зависимостей
- Если массив зависимостей не существует, обратный вызов срабатывает каждый раз, когда он отображается.
- Если массив зависимостей существует, обратный вызов выполняется только при его изменении.
let arr = [] // 一个数组,存储每一个hook
let index = 0 // 下标,存取每个hook对应的位置
function useState(init){
arr[index] = arr[index] || init // 如果存在则用之前的值
const cur = index // 设置一个变量存储当前下标
function setState(newState){
arr[cur] = newState
render() // 渲染,页面触发更新
}
return [arr[index++], setState]
}
function useEffect(callback, deps){
const hasNoDeps = !deps // 如果没有依赖,则直接每次更新
const lastDeps = arr[index] // 获取上一次的依赖数组
const hasChangeDeps = lastDeps
? !deps.every((e, i) => e === lastDeps[i]) // 如果每一项都相同
: true
if(hasNoDeps || hasChangeDeps){
callback()
arr[index] = deps
}
index++
}
Реагировать на новые функции
- Ленивый и неопределенность
import React, {Component, lazy, Suspense} from 'react'
const About = lazy(() => import(/*webpackChunkName: "about" */'./About.jsx'))
class App extends Component {
render() {
return (
<div>
// 我们需要用suspense来进行过渡,显示一个loading
<Suspense fallback={<div>Loading...</div>}>
<About></About>
</Suspense>
// 这样子是不行的,因为还没有加载完成不知道显示什么
<!--<About></About>-->
</div>
);
}
}
export default App;
- Границы ошибки
class App extends Component {
state = {
hasError: false,
}
static getDerivedStateFromError(e) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <div>error</div>
}
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<About></About>
</Suspense>
</div>
);
}
}
- React.памятка React.memo работает для функциональных компонентов, а не для компонентов класса
а такжеpureComponentпохоже, ноpureComponentкоторый предоставилshouldComponentUpdateОн просто сравнивает, изменился ли сам входящий реквизит, если внутреннее значение изменится, оно не будет обновлено. Например
class Foo extends PureComponent {
render () {
console.log('Foo render');
return <div>{this.props.person.age}</div>;
}
}
person: {
count: 0,
age: 1
}
// person.age++, 本来应该触发更新,但是不会因为props的第一级没有发生变化
В настоящее время мы можем использовать memo для его оптимизации.
const Foo = memo(function Foo (props) {
console.log('Foo render');
return <div>{props.person.age}</div>;
})
Первый параметр memo — это функциональный компонент, а второй — сshouldComponentUpdate类似это функция
(nextProps, nextState)=>{
}
- Преимущества крючков
- Функциональные компоненты не имеют этой проблемы
- Пользовательские хуки облегчают повторное использование логики состояния
- Разделение проблем побочных эффектов
- Легче писать и легче понять
- Недостатки крючков.
- Хуки могут запускаться больше раз, чем вы ожидаете
- Немного сложно поддерживать зависимости useEffect
Улучшение состояния реакции
Данные, обычно встречающиеся в дочерних компонентах, находятся в родительских компонентах.
// 父组件
class AllInput extends React.Component {
constructor(props) {
super(props)
this.state = { content: '' }
this.handleContentChange = this.handleContentChange.bind(this)
}
handleContentChange(newContent) {
this.setState({ content: newContent })
}
render() {
return (
<div>
<Input content={ this.state.content } onContentChange={ this.handleContentChange }/>
<br /><br />
<Input content={ this.state.content } onContentChange={ this.handleContentChange }/>
</div>
)
}
}
// 子组件
class Input extends React.Component {
constructor(props) {
super(props)
this.handleChange = this.handleChange.bind(this)
}
handleChange(e) {
setState(修改数据的方法)
this.props.onContentChange(e.target.value)
}
render() {
return (
<input type='text' value={ this.props.content } onChange={ this.handleChange } />
)
}
}
Функции высшего порядка
Функция высшего порядка — это то, что принимает одну или несколько функций и возвращает функцию.
Есть две основные функции
Риелтером
Прокси атрибута имеет три общие роли
- Реквизит для действий
function HigherOrderComponent(WrappedComponent) {
return class extends React.Component {
render() {
const newProps = {
name: '大板栗',
age: 18,
};
return <WrappedComponent {...this.props} {...newProps} />;
}
};
}
Таким образом, вы можете передавать пользовательские реквизиты дочерним компонентам.
- состояние извлечения
// 普通组件Login
import React, { Component } from 'react';
import formCreate from './form-create';
@formCreate
export default class Login extends Component {
render() {
return (
<div>
<div>
<label id="username">
账户
</label>
<input name="username" {...this.props.getField('username')}/>
</div>
<div>
<label id="password">
密码
</label>
<input name="password" {...this.props.getField('password')}/>
</div>
<div onClick={this.props.handleSubmit}>提交</div>
<div>other content</div>
</div>
)
}
}
//HOC
import React, { Component } from 'react';
const formCreate = WrappedComponent => class extends Component {
constructor() {
super();
this.state = {
fields: {},
}
}
onChange = key => e => {
const { fields } = this.state;
fields[key] = e.target.value;
this.setState({
fields,
})
}
handleSubmit = () => {
console.log(this.state.fields);
}
getField = fieldName => {
return {
onChange: this.onChange(fieldName),
}
}
render() {
const props = {
...this.props,
handleSubmit: this.handleSubmit,
getField: this.getField,
}
return (<WrappedComponent
{...props}
/>);
}
};
export default formCreate;
Например, таким образом можно извлечь состояние поля ввода.
- Управление ссылками
import React, { Component } from 'react';
const refHoc = WrappedComponent => class extends Component {
componentDidMount() {
console.log(this.instanceComponent, 'instanceComponent');
}
render() {
return (<WrappedComponent
{...this.props}
ref={instanceComponent => this.instanceComponent = instanceComponent}
/>);
}
};
export default refHoc;
Это даст вам пример компонента
Не может использоваться для компонентов без состояния (компоненты функционального типа)refs, потому что у компонентов без состояния нет экземпляров
обратное наследование
function HigherOrderComponent(WrappedComponent) {
return class extends WrappedComponent {
render() {
return super.render();
}
};
}
Обратное наследование — это функция, которая получает компонент в качестве параметра и возвращает класс, наследующий компонент.renderвнутренний вызовsuper.render()
- Состоянием можно манипулировать, но трудно поддерживать
- рендеринг угона
Перехват рендеринга, мы можем управлять рендерингом компонента и условно отображать компонент Например
- условный рендеринг
function withLoading(WrappedComponent) {
return class extends WrappedComponent {
render() {
if(this.props.isLoading) {
return <Loading />;
} else {
return super.render();
}
}
};
}
Это позволяет вам условно управлять рендерингом компонентов.
- Изменить вывод рендера
//hijack-hoc
import React from 'react';
const hijackRenderHoc = config => WrappedComponent => class extends WrappedComponent {
render() {
const { style = {} } = config;
const elementsTree = super.render();
console.log(elementsTree, 'elementsTree');
if (config.type === 'add-style') {
return <div style={{...style}}>
{elementsTree}
</div>;
}
return elementsTree;
}
};
export default hijackRenderHoc;
//usual
@hijackRenderHoc({type: 'add-style', style: { color: 'red'}})
class Usual extends Component {
...
}
Проблемы с ХОЦ
- статический метод отсутствует
- Атрибут refs не может быть прозрачно передан
- Обратное наследование не гарантирует полного разрешения дочерних компонентов.
Конвенция HOC
- держите реквизит последовательным
- Вы не можете использовать ссылки в функциональных (без сохранения состояния) компонентах, потому что они не
- не мутировать дочерние компоненты
- Имя пакета может быть добавлено для облегчения отладки.
- Не используйте HOC в рендере
Сценарии применения
- Контроль доступа
- повторное использование страницы
Коммуникация компонента React
- Родительский компонент передает свойства дочернего компонента
- Дочерний компонент вызывает функцию обратного вызова родительского компонента.
- использовать контекст
- Использование эмиттера событий
Почему стоит выбрать React, а не Vue
- React — это функциональная идея, логика состояния передается через параметры
- Используйте js для управления всем, css или что-то еще может использовать js
- Сообщество очень сильное, и многие функции выполняются сообществом вместе.
- Библиотека пользовательского интерфейса отличная
- JSX делает компоненты более читабельными, структура между компонентами более четкой.
- Поддержка рендеринга на стороне сервера, улучшенная SEO и производительность рендеринга
Связь между React и MVVM
- M(odal): соответствует жизненному циклу компонента, укажите эти данные
- v(iew): сгенерированный реальный дом, соответствующий виртуальному дому, а также стили и т. д.
- V(iew)-M(odal): JSX в соответствующем компоненте преобразует виртуальный дом в реальный через алгоритм сравнения.
Разница между односторонней и двусторонней привязкой в React
Как правило, двусторонняя привязка требуется только для элементов управления формы пользовательского интерфейса.
- Когда форма пользовательского интерфейса значения односторонней привязки изменяется, нам нужно вручную обновить состояние, то есть установить событие прослушивания.
onChangeЖдать - Двусторонняя привязка автоматически обновляется
Когда существует много взаимодействий с формами, данные односторонней привязки легче отслеживать, управлять и поддерживать, но для этого требуется написать больше кода.
33. CSRF и XSS
разница
- CSRF должен работать после входа в систему, XSS не нужен
- CSRF - запросить API страницы для достижения незаконных операций, XSS - это имплантат JS Script на текущую страницу для изменения содержимого страницы
CSRF
Межсайтовые поддельные запросы
После того, как пользователь входит на веб-сайт, создается файл cookie.Если в это время открывается новый веб-сайт, и веб-сайт возвращает некоторые вредоносные запросы, это CSRF-атака.
- профилактика
- Проверить ссылку http
- Добавьте подтверждение токена к адресу запроса
- Добавить проверку токена в заголовок запроса
XSS
Атаки с использованием межсайтовых сценариев обычно реализуются путем вставки вредоносного js-кода в веб-страницы. В основном делятся на три категории:
- Отражение: атака кода xss в URL-адресе запроса
- Тип хранилища: сценарий атаки хранится на сервере для распространения
- тип dom: изменить содержимое страницы через dom
- профилактика
- Входная фильтрация: например, фильтрация
<script>Ждать - Экранирование вывода: например.
<,>,/И т. д. символы преобразуются с помощью escape-символов - Использовать httponly: сделать js-скрипт недоступным для файлов cookie
- Попробуйте использовать метод post и ограничьте длину при использовании get
Суммировать
- Токен добавлен для предотвращения CSRF, а не XSS
- Атака CSRF связана с тем, что браузер автоматически добавляет файл cookie вместо собственного токена.
34. localStorage и sessionStorage и файлы cookie
localStorage
Жизненный цикл постоянный, можно хранить только строковые типы
- перекрестный домен Реализация с использованием iframe и postMessage
sessionStorage
Жизненный цикл заключается в том, что текущее окно или вкладка не закрываются, и как только они будут закрыты, все сохраненные данные будут удалены.
cookie
Жизненный цикл файлов cookie действителен до истечения срока действия и используется всеми окнами одного и того же источника в одном браузере.
свойства файлов cookie
- имя: вы должны определить имя файла cookie
- значение: обязательно, укажите значение куки
- expires: Укажите время истечения срока действия в формате UTC или GMT. Если файл cookie не установлен, он будет действителен только в текущем сеансе, и файл cookie будет удален при закрытии окна браузера.
- домен: укажите имя домена, на котором находится файл cookie. По умолчанию используется имя домена при установке файла cookie. Указанное доменное имя должно быть частью текущего отправляемого файла cookie. Файл cookie будет отправлен только в том случае, если имя посещенного домена совпадает атрибут домена.
- путь: указанный путь должен быть абсолютным путем. По умолчанию используется путь к веб-странице, которая запрашивает файл cookie. Файл cookie будет отправлен только в том случае, если атрибут пути совпадает с путем, отправленным на сервер. Пока атрибут пути совпадает часть пути отправки, например
path=/blog, путь отправки/blogrollОн также доступен. Атрибут пути помещения соответствует вступлению в силу свойства домена - Безопасный: Указывает cookie можно отправить только в зашифрованном протоколе HTTPS к серверу, если протокол связи автоматически открывается HTTPS
- max-age: используется для указания срока действия файла cookie, max-age имеет более высокий приоритет, чем expires
- httponly: атрибут httponly используется для установки того, что файл cookie не может быть доступен с помощью JavaScript, в основном для предотвращения кражи файла cookie инструментом xss.
Суммировать
- Разные браузеры не могут совместно использовать localStorage и sessionStorage
- Разные страницы одного и того же браузера могут использовать одно и то же локальное хранилище (страницы принадлежат одному и тому же доменному имени и порту).
- Информация о sessionStorage не может быть разделена между разными вкладками одного и того же браузера.
35. BFC и его роль
BFC — это контекст форматирования, который эквивалентен контейнеру.Элементы внутри и снаружи не влияют друг на друга.Способы создания следующие:
- корневой элемент html
- плаватьплавать
- Абсолютно позиционированные элементы position: fixed || absolute
- перелив не виден
- display is table, inline-block, flex
Основная роль принадлежит BFC
- очистить поплавок
- Предотвращение перекрытия полей между соседними элементами в одном BFC
- Элементы BFC и плавающие элементы не перекрываются
- BFC также вычислит плавающий элемент при вычислении высоты.
36. Реализовать (5).add(3).minus(2) функцию
Number.prototype.add = function(n) {
return this + n;
};
Number.prototype.minus = function(n) {
return this - n;
};
37. Непрерывное присвоение
пример 1:
var a = 3;
var b = a = 5;
=
var a = 3
var a = 5
var b = a
Итак, в конце a и b оба равны 5
Пример 2:
var a = { n: 1 }
var b = a
a.x = a = { n: 2 }
В начале и a, и b относятся к объектам{n:1}, а затем к оператору присваивания
Если появляется оператор присваивания.тогда он будет=Сначала выполняем, то есть сначала открываем место для a.x
То есть оба a и b теперь заменены на
{
n: 1,
x: {
n: 2
}
}
Далее идет присвоение a, a now становится
{
n: 2
}
38. отображение: нет, видимость: скрыто и непрозрачность: 0
-
display: none: не занимает места, на нем нельзя щелкнуть, обычно используется для скрытия элементов, что вызовет перекомпоновку, высокую производительность, ненаследуемые атрибуты и не может отображаться при изменении дочерних узлов (родительский элемент отсутствует) -
visibility: hidden: занимает место, нельзя щелкнуть, отображение не приведет к изменению структуры страницы, не будет растягиваться, это операция перерисовки, это унаследованный атрибут, и узлы-потомки могут отображаться путем модификации -
opacity: 0: занимает место, по нему можно щелкнуть, обычно используется с переходом
39. Производительность for и forEach
Для чего потому что
- for не имеет дополнительного стека вызовов функций и контекста
40. реактивный маршрутизатор<Link>а также<a>в чем разница
выключенСобытие тега по умолчанию, он будет обновлять только содержимое соответствующей страницы, не обновляя всю страницу. Он использует историю для перехода, что изменит URL-адрес, но не обновит страницу.41. Контекст выполнения
- глобальный контекст выполнения: Контекст по умолчанию, любой код не внутри функции находится в глобальном контексте. Он делает две вещи: создает глобальный объект окна и устанавливает его в глобальный объект. Программа имеет только один глобальный объект
- контекст выполнения функции: Каждый раз, когда вызывается функция, для функции создается новый контекст, каждая функция имеет свой собственный контекст, но создается при вызове функции. Контекстов функций может быть любое количество.Каждый раз, когда создается новый контекст выполнения, он выполняет серию шагов в определенном порядке.
-
Контекст выполнения функции Eval: выполнить на
evalКод внутри функции имеет свой собственный контекст выполнения
42. Стек выполнения
Стек выполнения — это стек вызовов, представляющий собой стек структур данных «последний вошел — первый обслужен», используемый для хранения контекста выполнения, созданного при выполнении кода.
let a = 'Hello World!';
function first() {
console.log('Inside first function');
second();
console.log('Again inside first function');
}
function second() {
console.log('Inside second function');
}
first();
console.log('Inside Global Execution Context');
43. Создайте контекст выполнения
в два этапа
- создать сцену
- этап выполнения
создать сцену
Контекст выполнения создается до выполнения кода, произойдут три вещи
- эта привязка
- Создайте компоненты лексической среды
- Создайте переменный компонент среды
эта привязка
В глобальном контексте выполнения это указывает на глобальный объект
В контексте выполнения функции это зависит от того, как была вызвана функция. Если он вызывается ссылочным объектом, то this будет установлено на этот объект. иначе глобальный объект
let foo = {
baz: function() {
console.log(this);
}
}
foo.baz(); // 'this' 引用 'foo', 因为 'baz' 被
// 对象 'foo' 调用
let bar = foo.baz;
bar(); // 'this' 指向全局 window 对象,因为
// 没有指定引用对象
Лексическое окружение
— это лексическая вложенная структура кода, которая определяет идентификаторы и ассоциируется с определенными переменными и функциями. используется для хранения объявлений функций иlet, constОбъявленная привязка переменных
переменная среда
Это также лексическая среда, используемая для храненияvarпривязка переменных
let a = 20;
const b = 30;
var c;
function multiply(e, f) {
var g = 20;
return e * f * g;
}
c = multiply(20, 30);
Контекст выполнения функции создается только при вызове функции multipy, сначала пусть и const не будут связаны ни с каким значением, но var уже будет иметь значение undefined, о чем часто говорятПодъем объявления переменной
44. Цикл событий
Есть два типа заданий
- Синхронизировать задачу
- асинхронная задача
задача макроса
- код тела
- setTimeout
- setInterval
- setImmediate
- requestAnimationFrame
микрозадачи
- process.nextTick
- mutation.observer
- Promise.then cath finally
45. ссылка и @import
- ссылка принадлежит тегу html, @import принадлежит предоставленному css
- Ссылка загружается при загрузке страницы, а @import должен ждать загрузки страницы перед загрузкой css.
- ссылка не имеет проблем с совместимостью
- ссылка имеет больший вес
46. Перекрывающиеся поля
- Когда два соседних поля положительны, эффект коллапса больше между двумя
- Когда два соседних поля отрицательны, эффект коллапса является наибольшим по абсолютной величине.
- Когда два поля являются положительными и отрицательными, эффект суммируется
47. Прогрессивное улучшение и изящное улучшение
- прогрессивное улучшение: Создавайте страницы для браузеров с низкими версиями, чтобы обеспечить самые основные функции, а затем улучшайте эффекты и взаимодействие для продвинутых браузеров.
- элегантное улучшение: Создавайте полные функции с самого начала, а затем обеспечивайте совместимость с браузерами более ранних версий.
Отличие: прогрессивное улучшение совместимо вверх, элегантное улучшение совместимо вниз.
48. Немедленно выполнять функции
эффект
- Не нарушайте глобальное пространство имен
- Чтобы использовать, передайте переменную
(function(x){
console.log(x);
}(12345))
49. HTTP2.0 и HTTP1.1
HTTP2.0
- Базовая единица HTTP2.0 — двоичная, раньше она была в текстовом виде, и ее надежность была не очень хорошей, теперь используется двоичный формат, который более удобен и надежен.
- Мультиплексирование HTTP2.0 обрабатывает несколько запросов как несколько потоков, данные ответа на запрос делятся на несколько кадров, а кадры в разных потоках чередуются, что решает проблему большого количества TCP-соединений и медленного TCP-соединения, поэтому для того же доменного имени Просто создайте подключение
- HTTP2.0 сжимает заголовок сообщения, избегает передачи повторяющихся заголовков запросов и уменьшает размер передаваемых данных.
- Нажатие сервера HTTP2.0, после того как браузер отправит запрос, сервер будет активно отправлять ресурсы, связанные с запросом, и тогда браузеру не нужно снова отправлять последующие запросы.
- HTTP2.0 может установить приоритет запроса и может решить проблему блокировки в соответствии с приоритетом
HTTP1.1
- Обработка кеша добавляет заголовки кеша, такие как etag и if-none-match, для управления кешем.
- Длинные соединения, которые могут отправлять несколько запросов и ответов по TCP-соединению.
50. Разница между анимацией css и анимацией js
- хорошая производительность css
- Логика кода css относительно проста
- js управление анимацией хорошее
- js совместимость с анимацией хорошая
- js может добиться большего количества анимации
- js может добавлять события
51. Атрибуты offset, client и scroll
- клиент: отступы + контент — полоса прокрутки
- смещение: заполнение + содержимое + граница
- Прокрутка: заполнение + реальный контент
52. Заголовок измельченного кода
- Введите корневой узел, распечатайте путь метки и максимальное значение data-v на пути.
const root = document.getElementById("root");
function walk(node, path, max) {
if (!node) {
return;
}
path = [...path, node.tagName];
max = Math.max(max, node.dataset.v);
console.log(path, max);
for (let child of node.children) {
walk(child, path, max);
}
}
walk(root, [], -1)
...
<div id="root" data-v="3">
<p data-v="1">p1</p>
<span data-v="2">
span1
<span data-v="4">span2</span>
<span data-v="5">
<p>1</p>
</span>
</span>
<p data-v="99">p2</p>
</div>
- Реализовать функцию составления
var arr = [func1, func2, func3];
function func1(ctx, next) {
ctx.index++
next();
}
function func2(ctx, next) {
setTimeout(function () {
ctx.index++
next();
});
}
function func3(ctx, next) {
console.log(ctx.index);
}
compose(arr)({ index: 0 });
function compose(arr) {
return function (ctx) {
if (arr.length !== 0) {
let func = arr.shift()
func(ctx, next)
}
function next() {
if (arr.length !== 0) {
let func = arr.shift()
func(ctx, next)
}
}
}
}
- лупа
53. Поля и отступы встроенных элементов
- горизонтальное направление: Оба действительны в горизонтальном направлении
- вертикальное направление: В вертикальном направлении это недопустимо, но padding-bottom, padding-top покажет эффект, но высота не будет растягиваться, и это не повлияет на окружающие элементы.
54. Строчные и блочные элементы
- Встроенные и блочные элементы могут быть преобразованы друг в друга
- Встроенные элементы будут расположены в горизонтальной линии, она будет блокировать уровень в новой строке
- Элементы в строке не могут быть установлены на высоту, но могут быть установлены на высоту строки.
- Установка полей и отступов в вертикальном направлении встроенного элемента недопустима. Отступы отображаются в вертикальном направлении, но не растягиваются и не влияют на другие элементы.
- Уровень блока может содержать встроенные элементы и элементы уровня блока, встроенные элементы могут содержать только встроенные элементы и текст.
55. Как рассчитываются проценты полей, заполнения и перевода?
- margin: рассчитывается по ширине родительского элемента
- padding: рассчитывается по ширине родительского элемента
- перевести: рассчитывается по собственной ширине и высоте
56. дисплей: разрыв между элементами встроенного блока
причина
inline-blockвнешнеinline, внутри естьblock, который анализирует последовательные символы пробела как один пробел
Решение
- удалить пробелы
- Настройки родительского элемента
font-size: 0 - Настройки родительского элемента
letter-spacing: -4px - настройки дочернего элемента
vertical-align: bottomубрать вертикальный зазор
57. Принцип HTTPS
HTTP — это передача открытого текста, и каждая ссылка передачи может быть украдена или изменена третьей стороной. В частности, данные HTTP проходят через уровень TCP, а затем проходят через маршрутизатор WIFI, оператора и целевой сервер, и данные могут быть получены посредником и подделаны.Это часто говорятатака «человек посередине»
HTTPS — это расширенная версия HTTP. использоватьСимметричное шифрованиеа такжеАсимметричное шифрованиеКомбинированный способ защиты безопасности связи между браузером и сервером. Алгоритм симметричного шифрования для шифрования данных + алгоритм асимметричного шифрования для обмена ключами + цифровой сертификат для проверки личности = безопасность
HTTPS состоит из двух частей: HTTP + SSL/TLS, то есть к HTTP добавляется дополнительный слой модулей, обрабатывающих зашифрованную информацию. Передача информации между сервером и клиентом будет зашифрована через TLS, поэтому передаваемые данные являются зашифрованными данными.
процесс шифрования
Сначала браузер отправляетclient_randomи список методов шифрования
После того, как сервер принимает его, он возвращает браузеру другое случайное число.server_randomи метод шифрования
Теперь у обоих есть три одинаковых учетных данных:client_random, server_randomа также加密方法
Затем используйте этот метод шифрования, чтобы смешать два случайных числа для генерации ключа, который браузер связывает с сервером.暗号охватывать
Симметричное и асимметричное шифрование
-
Симметричное шифрование является самым простым методом, что означает, что для шифрования и дешифрования используется один и тот же ключ.Преимущество заключается в том, что конфиденциальность сообщения гарантируется, но недостаток заключается в том, что ключ может быть утерян.
-
Асимметричное шифрование означает, что при наличии двух ключей, A и B, пакеты данных, зашифрованные с помощью A, могут быть расшифрованы только с помощью B, тогда как пакеты данных, зашифрованные с помощью B, могут быть расшифрованы только с помощью A. Когда клиент отправляет сообщение, сначала используется ключ для шифрования, а затем сервер использует закрытый ключ для расшифровки. Но поскольку открытый ключ не хранится в секрете, его можно украсть, а сообщение можно подделать.
Цифровые сертификаты и цифровые подписи
Чтобы решить проблему ненадежности источника открытого ключа в асимметричном шифровании. Мы можем решить эту проблему с помощью цифровых сертификатов и цифровых подписей.
Сначала сгенерируйте пару ключей локально и перейдите в ЦС, чтобы подать заявку на цифровой сертификат с помощью открытого ключа.
-
цифровой подписи: после того, как центр сертификации получит информацию, он зашифрует информацию с помощью алгоритма одностороннего хеширования, а затем сгенерирует дайджест, а затем центр сертификации зашифрует дайджест своим собственным закрытым ключом, и конечным результатом будет цифровая подпись.
-
Цифровой сертификат: Наконец, центр сертификации объединит запрошенную информацию и цифровую подпись для создания цифрового сертификата, который на самом деле является открытым ключом.
-
Как работают цифровые сертификаты:
- Клиент расшифровывает цифровой сертификат с помощью открытого ключа центра сертификации.Если источник цифрового сертификата является законным, после успешного расшифрования клиент получает дайджест информации. Затем клиент сгенерирует сводку информации о приложении в соответствии с тем же алгоритмом хеширования, что и ЦС.
- Затем сравните его с расшифрованным дайджестом.Если содержимое полное, значит, оно не было подделано. Клиент может получить открытый ключ сервера из сертификата и взаимодействовать с сервером посредством безопасного асимметричного шифрования. Таким же образом сервер может получить открытый ключ клиента.
процесс рукопожатия
- Клиент подает заявку на https-связь для отправки случайного числа, а также метода шифрования.
- Сервер отвечает, а затем отправляет клиенту цифровой сертификат (открытый ключ) и случайное число клиенту.
- Клиент TLS проверяет сертификат, получает открытый ключ, генерирует случайное значение, если нет проблем, а затем шифрует его с помощью открытого ключа и передает на сервер.
- Получив его, сервер расшифровывает его закрытым ключом и получает симметричный ключ, после чего информация может быть передана через этот ключ, после чего устанавливается канал соединения SSL.
- Обмен общими ключами прошел успешно, и клиент и сервер начали шифрованную связь.
- Отключить
客户端: 你好,我要发起一个 HTTPS 请求,请给我公钥
服务器: 好的,这是我的证书,里面有加密后的公钥
客户端: 解密成功以后告诉服务器: 这是我的 (用公钥加密后的) 对称秘钥。
服务器: 好的,我知道你的秘钥了,后续就用它传输。
использовать
Шифрование и дешифрование HTTPS занимает много времени и потребляет много ресурсов, если требования безопасности не очень высоки, его можно не использовать.
58. setImmediate() и process.nextTick()
- setTimeout выполняется по истечении указанного времени
- setImmediate предназначен для выполнения сразу после завершения текущей фазы опроса. При использовании в одном и том же цикле ввода-вывода setImmediate всегда вызывается первым.Его преимущество в том, что если он запланирован в цикле ввода-вывода, он будет выполнен перед всеми таймерами. То, как он выполняет, является хвостом текущей очереди задач.
- process.nextTick срабатывает в конце текущего стека выполнения, перед следующим циклом событий, всегда перед асинхронным.
Зачем использовать process.nextTick(), потому что вы можете разрешить пользователю обрабатывать ошибки или повторить запрос до того, как цикл обработки событий продолжится.
59. Цикл событий браузера и узла
Задачи браузера делятся назадача макросаа такжемикрозадачи
- Задачи макроса: код в сценарии, setTimeout, setInterval, ввод-вывод, визуализация пользовательского интерфейса.
- Микрозадачи: обещание, Object.observe, MutationObserver
Узлы делятся на следующие категории:
- микрозадача: микрозадача
- следующийTick: процесс.nextTick
- таймеры: различные таймеры
- Обратный вызов ввода-вывода: есть ли функция обратного вызова для завершенной операции ввода-вывода, остаток от предыдущего раунда обучения, выполняет почти все обратные вызовы, но не включает закрытие, таймеры и setImmediate
- бездействие, подготовка: используется только для внутреннего использования
- Опрос: Ожидание новых событий ввода / вывода, он будет заблокирован здесь из-за времени окончания таймеров и событий тайм-аута и т. Д.
- проверка: выполнить обратный вызов setImmediate
- обратный вызов close: закрывает все дескрипторы закрытия, некоторые события onclose
В среде узла
Перед циклом выполняются следующие операции:
- Синхронизировать задачу
- сделать асинхронный запрос
- Запланируйте время, когда таймер вступит в силу
- Выполнить process.nextick()
начать цикл Действия в цикле:
- Очистить очередь таймеров, очистить очередь nextTick, очистить очередь микрозадач
- Очистить очередь ввода-вывода, очистить очередь nextTick, очистить очередь микрозадач
- Очистить очередь проверки, очистить очередь nextTick, очистить очередь микрозадач
- Очистить очередь закрытия, очистить очередь nextTick, очистить очередь микрозадач
разница
- Таймеры setTimeout в среде узла будут выполняться вместе последовательно, а браузеры будут разделены один за другим.
- Выполнение микрозадач в среде браузера происходит после выполнения каждой макрозадачи, в то время как микрозадачи в узле будут выполняться между различными этапами, а mircroTask будет выполняться сразу после завершения этапа.
Суммировать
В среде браузера:
while(true){
宏任务队列.shift()
微任务队列全部任务()
}
В среде узла:
while(true){
loop.forEach((阶段)=>{
阶段全部任务()
nextTick全部任务()
microTask全部任务()
})
}
60. React Fiber
Первоначально использовался Reactstack reconcilerАлгоритм планирования. Страница может зависнуть, потому что React сразу же начнет процесс согласования после setState, он будет проходить, чтобы найти разницу, и он будет отображаться только после того, как все виртуальные домы будут пройдены. В процессе согласования основной поток занят js, поэтому взаимодействие и верстка остановятся, и он застрянет.
Теперь для оптимизации используется Fiber reconciler.
- разделение задач
- Обновление Пауза, Прекращение и Повторное использование
- Установить приоритет
- render может возвращать несколько элементов
Scheduler
Планирование — это процесс согласования оптоволокна
Если пользовательский интерфейс должен работать хорошо, необходимо учитывать и другие факторы.
- Не все состояния нужно обновлять немедленно, например, в пределах видимого диапазона.
- Не все обновления имеют одинаковый приоритет, например, пользовательский ввод имеет приоритет над запросом отображения ресурса.
- Высокоприоритетные должны прерывать низкоприоритетные обновления
Таким образом, процесс согласования заключается в том, чтобы выполнять только одну небольшую задачу за раз и проверять, есть ли какие-либо высокоприоритетные задачи, которые необходимо обработать после завершения.
Структура данных волокна
- возврат: родительский узел
- дочерний: первый дочерний узел
- Ситунг: родной соус
fiber {
stateNode: {},
child: {},
return: {},
sibling: {},
}
разделение задач
Блоки разветвления оптоволокна разбиваются в соответствии с узлами виртуального дома, потому что дерево оптоволокна строится в соответствии с виртуальным домом.
задача приостановлена
Fiber использует API-интерфейсы браузераrequestIdleCallbackразрешить браузеру выполнять определенные задачи, когда он бездействует
function fiber(剩余时间) {
if (剩余时间 > 任务所需时间) {
做任务;
} else {
requestIdleCallback(fiber);
}
}
использоватьrequestAnimationFrameПриходите оказать анимацию
приоритет
{
Synchronous: 1, // 同步任务,优先级最高
Task: 2, // 当前调度正执行的任务
Animation 3, // 动画
High: 4, // 高优先级
Low: 5, // 低优先级
Offscreen: 6, // 当前屏幕外的更新,优先级最低
}
61. процесс вебпака
- Инициализация: чтение и объединение параметров из файла конфигурации, затем создание экземпляра плагина.
new Plugin() - Начать компиляцию: инициализировать с параметрами, полученными на предыдущем шаге.
Complierплагин загрузки объекта, выполнитьCompiler.runначать компиляцию - Определение входа: конфигурация
entryНайти все входные файлы - Скомпилируйте модуль: из
entryзапускаем, вызываем настроенныйloader, преобразовать модуль и найти модули, от которых зависит модуль, рекурсивно, пока не будут найдены все зависимые модули - Полная компиляция модуля: этот шаг был использован
loaderПреобразованы все модули, чтобы получить новый контент и зависимости после преобразования. - Выходные ресурсы: в соответствии с зависимостями между записью и модулем, собранным в
chunkБлок кода, список выходов Makefile - Успешный вывод: В соответствии с выходным путем и именем файла в конфигурации запишите файл в систему и завершите сборку
62. Горячее обновление вебпака
основная зависимостьwebpack, express, websocket
- использовать
expressЗапустите локальную службу и ответьте, когда браузер получит к ней доступ - Использование сервера и клиента
websocketдолгосрочная связь -
webpackМониторинг изменений исходного файла- После завершения каждой компиляции будет сгенерированhashзначение, json-файл модифицированного модуля, js-файл модифицированного кода модуля
- После компиляции пройти
socketОтправьте текущее скомпилированное хеш-значение клиенту
- клиента
websocketПрослушивание хеш-значения, вызванного изменениями файла, будет сравниваться с последним временем.- Последовательный и кэш-память
- Если это несовместимо, получите последние ресурсы через ajax и jsonp.
- Используйте файловую систему в памяти для замены измененного содержимого для локальных обновлений.
63. Разница между CommonJs и модульностью ES6
- CommonJs поддерживает динамический импорт, ES6 — нет.
- CommonJs — синхронный импорт, ES6 — асинхронный импорт
- Когда CommonJs импортируется, это копия значения. Если экспорт изменится, он не изменится, но будет ссылка на ES6. Если экспорт изменится, импортированная часть также изменится.
Применение
- Экспорт: CommonJs
module.exports, ES6 естьexport / export default - Импорт: CommonJs
const x = require('xx'), ES6 естьimport xx from 'xxx'
64. Стрелочные функции и нормальные функции
Обычная функция
- Обычно это указывает на окно глобального объекта
- При вызове в качестве метода объекта это указывает на объект
- При использовании в качестве конструктора это относится к новому объекту
- Это можно изменить, позвонив и применив
стрелочная функция
- это всегда относится к лексической области видимости
- Невозможно изменить это с помощью вызова и применения
65. Узел читает файл и преобразует его в буфер
const fs = require('fs')
const path = require('path')
const mimeType = require('mime-types') // 文件类型
const filePath = path.resolve('./01.png')
const data = fs.readFileSync(filePath)
const buffer = new Buffer(data).toString('base64')
const base64 = `data:${mimeType.lookup(filePath)};base64,${buffer}`
console.log(base64)
66. функция сортировки
- Сортировка вставками используется для массивов с числами меньше 10.
- Массивы с числами больше 10 используют быструю сортировку
67. Замыкания и самовыполняющиеся функции
Закрытие
преимущество
- Вы можете постоянно хранить локальные переменные в памяти
- Глобальных переменных можно избежать
недостаток:
- Занимает больше памяти, что может привести к утечкам памяти
самовыполняющаяся функция
- Избегайте загрязнения именования областей
- Повысьте производительность и уменьшите количество поисковых запросов
- Избегайте глобальных конфликтов имен
- Сохранить состояние закрытия
разница
- Немедленное выполнение Функция выполняется сразу после ее объявления, обычно используется только один раз.
- Замыкания в основном позволяют внешним функциям получать доступ к внутренним переменным и уменьшают использование глобальных переменных.
68. 0,1 + 0,2! == 0,3
JS использует стандарт двойного точности IEEE 754 для расчета. Если он сталкивается с неделимым десятичным десятичным, он возьмет приблизительное значение. Если это достаточно близко, это будет считано, что значение.
69. Реагировать на рендеринг на стороне сервера
Рендеринг на стороне сервера — это когда React преобразует Node.js в HTML и возвращает его в браузер.Этот процесс называется «изоморфизмом», поскольку большая часть кода приложения может выполняться как на сервере, так и на клиенте.
преимущество
По сравнению с традиционными одностраничными приложениями SPA,
- Лучшее SEO, потому что инструменты для сканирования, такие как поисковые системы, могут напрямую просматривать полностью обработанные страницы.
- Лучшее взаимодействие с пользователем, рендеринг сервера в порядке, если сеть работает медленно или устройство работает медленно.
недостатки
- Поскольку браузер с сервером отличается, документ, окно и т. Д. Не могут быть получены, будет жаловаться
- Сервер будет занимать больше памяти
70. Принцип фронтальной маршрутизации
- За хеш-режимом следует #.Независимо от того, как изменится значение хеш-функции, сервер получит URL-адрес только до #.
hashchangeСобытие, переключение страниц по хешу - Режим истории в основном использует history.pushState и history.replaceState для изменения URL-адреса. Изменение URL-адреса приведет только к обновлению истории браузера и не приведет к обновлению страницы.
popstateдля изменения содержимого страницы при отключении события тега a по умолчанию.
Режим хеширования не требует внутренней настройки и обладает хорошей совместимостью.Режим истории требует внутренней конфигурации для использования.
71. Принцип Мобкса
- низкая сложность разработки
- небольшое количество кода
- Хорошая производительность рендеринга
Принцип работы
- Определение государства заставляет его статьнаблюдаемыйиз
- Создайте производные, чтобы реагировать на изменения состояния
- Используйте действие для изменения состояния
Принципы дизайна
Mobx поддерживает односторонний поток данных, действия изменяют состояние, а обновления состояния изменяют представления.
- Mobx сохраняет все порождения в согласованном состоянии, не кэшируя данные и не пересчитывая их при необходимости.
- Производные, не участвующие в реакции, будут просто выброшены в мусор
Mobx запускается синхронно и имеет 2 преимущества.
- не получит старые производные
- Было бы проще отслеживать стек
Основное использование аautoRun, эта функция может инициировать обратный вызов при изменении используемого нами свойства, и обратный вызов не будет выполняться при изменении неиспользуемого свойства.
72. Принцип реализации Object.create()
По сути, это создание нового объекта, а затем перезапись прототипа объекта на входящий объект-прототип (аналогично наследованию)
function(constructor){
const F = function(){}
F.prototype = constructor
const res = new F()
return res
}
73. Проникновение события
установить свойства css3pointer-events: none
74. Общие коды статуса http
- 200: успех, нормальная обработка и возврат
- 204: Обработка прошла успешно, но возвращенная информация тела не имеет содержания.
- 301: Постоянное перенаправление, запрошенный ресурс назначается другому URL-адресу.
- 302: временное перенаправление, я надеюсь, что это посещение может получить ресурсы через другой URL-адрес.
- 303: следует использовать get для доступа к другому URL-адресу
- 304: указывает, что кэш согласования доступен.
- 400: В запросе есть синтаксическая ошибка.
- 401: Несанкционировано, проверить
- 403: доступ запрещен, недостаточно прав
- 404: Ресурс доступа не существует
- 500: запрос ненормальный, это также может быть ошибка интерфейса.
- 503: Сервер отключен на техническое обслуживание и не может обработать запрос.
75. блокировка js, css
js асинхронная загрузка и отложенная загрузка не блокируют отрисовку страницы и загрузку ресурсов
- defer будет загружен по порядку, async не по порядку
- defer означает, что все страницы проанализированы и запущены, а загрузка отложена и выполняется немедленно.
- Выполнять сразу после завершения асинхронной загрузки
- Если указано одновременно, асинхронный имеет более высокий приоритет
Встроенный и внешний js
- Встроенный js заблокирует загрузку всех ресурсов
- Внешний js будет блокировать последующий рендеринг контента и загрузку ресурсов
css
- CSS не будет блокировать синтаксический анализ DOM, но заблокирует рендеринг, потому что дерево рендеринга будет отображаться только в том случае, если дерево DOM объединяется с деревом стилей для создания дерева рендеринга.
- css заблокирует последующее выполнение инструкции js
Если за css следует встроенный js, возникнет ситуация блокировки, потому что браузер будет поддерживать порядок css и js, а таблица стилей должна быть загружена до встроенного js.
порядок загрузки
- js будет выполняться сразу в голове, блокируя последующую загрузку и выполнение ресурсов. Поскольку js может изменить dom, если он не заблокирован, порядок операций dom не поддается контролю.
- Выполнение js зависит от css. js будет выполняться только после того, как все предыдущие css будут загружены
Уведомление
- CSS нужно размещать в голове, чтобы он мог как можно быстрее отреагировать и отрендерить страницу, ведь он не будет блокировать загрузку ресурсов
- js следует размещать в нижней части тела, чтобы DOM можно было отобразить как можно быстрее, чтобы избежать блокировки DOM.
- css заблокирует выполнение js, он не заблокирует загрузку js, но js не будет выполняться, пока css не будет загружен и воспроизведен
Прежде чем код JS будет выполнен, браузер должен убедиться, что все стили CSS перед JS проанализированы, иначе он будет перепутан.Предыдущие стили CSS могут перезаписать стили элементов, определенные в файле JS, что CSS блокирует последующее выполнение JS. , первопричина.
76. Неявные преобразования
- Числовые операторы
- точечный оператор
- внутри оператора if
- = =
77. Реагируйте на оптимизацию выше сгиба
- Использовать кеш браузера
- JS-сжатие веб-пакета, сжатие html
- Извлечь общедоступные ресурсы
- Webpack модифицирует среду разработки для производственной среды.
- Использовать спрайт
- использовать cdn
78. Object.assign
Если объект имеет только один слой, это глубокая копия, если у него несколько слоев, это поверхностная копия.
const obj1 = {
a: 1,
b: {
c: 2
}
}
const obj2 = Object.assign({}, obj1)
console.log(obj1 == obj2)
console.log(obj1, obj2)
obj1.b = 2
console.log(obj1 == obj2)
console.log(obj1, obj2)
79. ВнутреннийHtml и внешнийHtml
- внутренний находится внутри этикетки, внешний - включенная этикетка
80. рем и эм
- rem основан на размере шрифта корневого элемента
- em определяется по размеру шрифта собственного элемента, если его нет, то он может наследовать размер шрифта от родительского элемента.
81. Сборка мусора и утечки памяти
вывоз мусора
- пометить как очищенный
Наиболее часто используемый метод сборки мусора, он помечает переменные во время работы. Если переменные в среде больше не могут получить доступ к этим переменным, они будут очищены.
var m = 0,n = 19 // 把 m,n,add() 标记为进入环境。
add(m, n) // 把 a, b, c标记为进入环境。
console.log(n) // a,b,c标记为离开环境,等待垃圾回收。
function add(a, b) {
a++
var c = a + b
return c
}
Например, локальные переменные и параметры функций, к которым нет доступа извне, будут очищены.
- подсчет ссылок
Определить количество ссылок на ресурс
var arr = [1, 2, 3, 4];
arr = [2, 4, 5]
Например в начале[1,2,3,4]Количество ссылок равно 1 и не будет очищено, но ссылка arr изменена ниже,[1,2,3,4]счетчик ссылок станет равным 0 и будет очищен
утечка памяти
- неожиданная глобальная переменная
function foo(arg) {
bar = "this is a hidden global variable";
}
Таким образом, бар будет объявлен в глобальной переменной и не будет выпущен.
-
таймер При использовании
setIntervalа не закрытый он всегда будет существовать и его не выпустят -
Закрытие Замыкания поддерживают локальные переменные и не могут быть освобождены
-
ссылки на dom не очищаются Если ссылка на элемент dom не очищена, он всегда будет существовать
оптимизация
- Оптимизация массива
var arr = [1,2,3]
arr.length = 0 // 这样子优化可以不用新生成一个空数组
- повторное использование объекта
var t = {}
while(){
t.a = 1
}
t = null
Попробуйте повторно использовать объект, чтобы не генерировать его каждый раз, а затем установить его в значение null, когда он будет израсходован, сборка мусора
- Перебор функциональных выражений
function t(){
}
while(){
t()
// var t = function(){} 这样子就不用循环创建很多函数了
}
82. Рукописные обещания и Promise.all
Promise
Ниже приведен сокращенный вариант
function myPromise(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
let reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
// 声明返回的promise2
let promise2 = new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
onFulfilled(this.value)
};
if (this.state === 'rejected') {
onRejected(this.reason)
};
if (this.state === 'pending') {
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value)
})
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
}
});
// 返回promise,完成链式
return promise2;
}
new myPromise((resolve, reject) => {
console.log('1')
resolve(1)
console.log('2')
}).then((res) => {
console.log(res)
console.log('4')
return 2
})
Promise.all
const myPromiseAll = function (promiseList){
const result = []
return new Promise((resolve, reject) => {
let index = 0
next()
function next(){
promiseList[index].then((res) => {
result.push(res)
index++
if(index === promiseList.length){
resolve(result)
} else {
next()
}
})
}
})
}
83. Почтовый метод
- application/x-www-form-urlencoded (параметры передачи URL)
- multipart/form-data (загрузить файл)
- приложение/json (передать json)
- text/xml
84. Предварительный запрос параметров http
Перед официальным кроссдоменом будет инициирован и предварительно проверен опционный запрос. Определите, является ли отправленный запрос безопасным, и одновременно отправьте адрес запроса и метод запроса.Сервер определяет, находится ли исходное доменное имя в списке разрешений.Если метод запроса не поддерживается, запрос разрешен.
Предварительная проверка будет отправлена только для сложных запросов, следующие сложные запросы
- один из поставить/удалить/исправить/постить
- Отправить в формате json (тип содержимого: application/json)
- В запросе есть настраиваемые заголовки
Зачем предварительно проверять?Сложные запросы могут иметь побочные эффекты на сервере, модификации данных и т. д. Поэтому проверьте, находится ли источник запроса в списке разрешенных или нет.
85. Три характеристики oop
- упаковка
- наследовать
- полиморфизм
86. Рукописный предел параллелизма
function limitPromise(taskList, limit) {
return new Promise((resolve, reject) => {
let index = 0
let active = 0
let finish = 0
let result = []
function next() {
if (finish >= taskList.length) {
resolve(result)
return
}
while (active < limit && index < taskList.length) {
active++
let cur = index
taskList[index].then((res) => {
active--
finish++
result[cur] = res
next()
})
index++
}
}
next()
})
}
87. Сотрясение дерева Webpack
Встряхивание дерева — это способ удалить бесполезный код, и он автоматически интегрируется после запуска webpack3/4.
88. getComputedStyle и стиль
- getComputedStyle доступен только для чтения, стиль доступен для чтения и записи.
- style может получать только встроенные стили
window.getComputedStyle(dom, null).getPropertyValue('display')
89. Странная блочная модель
-
Стандартная блочная модель: размер = содержимое + поле + отступ + граница.
-
Странная блочная модель: размер = ширина (содержимое + отступы + граница) + поля
-
content-box: по умолчанию, стандартная блочная модель
-
border-box: граница и отступ учитываются по ширине
.container {
display: flex;
width: 200px;
height: 50px;
}
.item1 {
width: 50%;
background: red;
border: 10px solid black;
}
.item2 {
width: 50%;
background: yellow;
}
<div class="container">
<div class="item1">1</div>
<div class="item2">2</div>
</div>
Эффект показан на рисунке
Предположим теперь, что два дива размещены на линии, оба шириной 50%, если мы добавим бордюр к одному из них, то другой будет сжат
В этот момент мы можем установить размер коробки дляborder-box
.item1 {
width: 50%;
background: red;
border: 10px solid black;
box-sizing: border-box;
}
Нет проблем с сжиманием.
90. Object.defineProperty
Object.defineProperty(obj, prop, descriptor)
MDN描述:
obj要在其上定义属性的对象。
prop要定义或修改的属性的名称。
descriptor将被定义或修改的属性描述符。
- значение: установить значение
- записываемый: может ли он быть переопределен
- enumberable: можно ли перечислить (for..in, Object.keys)
- set/get
- настраиваемый: можно ли его переопределить
91. Как HTTP повторно использует соединения
Установите заголовок http:Connection: keep-alive, Сообщает серверу, должен ли я запрашивать, снова избегая трехэтапного рукопожатия
92. Связь между HTTP и TCP
- http — это прикладной уровень, tcp — транспортный уровень.
- http реализован на базе tcp
- tcp — это простое соединение, а http — для отправки и получения данных.
93. Преимущества узла
- Полностью js синтаксис
- Высокий параллелизм — это хорошо
- Неблокирующий ввод-вывод
- Короткий цикл разработки
- один процесс, один поток
94. Структура HTTP-сообщения
- Сообщение запроса: строка запроса, заголовок запроса, пустая строка, данные запроса
- Ответное сообщение, строка состояния, заголовок, пустая строка, тело ответа
заголовок запроса
- Метод запроса: получить/отправить
- хост: запрашивающий хост
- подключение: статус подключения
- кеш-контроль: кеш
- accept: тип, который может быть отправлен
- пользовательский агент: агент
- ссылка: URL запрошенного ресурса
- accept-encoding: Поддерживаемые кодировки
- куки: куки
заголовок ответа
- дата: время ответа
- last-modify: время последней модификации
- etag: идентификатор ресурса
- подключение: статус подключения
- тип контента: тип ресурса
95. async / await
async
async всегда возвращает обещание
- Если return не отображается, верните promise.resolve(undefined)
- Если возврат не является обещанием, верните promise.resolve(data)
- Если вы вернете обещание, вы получите обещание
await
- await можно использовать только в асинхронном режиме
- Если промис не ждет, приобретается значение разрешения
Отличие от генератора
async — синтаксический сахар для генераторов
Улучшение асинхронности по сравнению с генератором
- Встроенный исполнитель, не нужно рядом выполнять
- лучшая семантика
- Вернуться к обещанию, вы можете продолжить операцию
96. Существует ли трехстороннее рукопожатие для каждого запроса?
Если кеша нет, устанавливается заголовок запросаconnection:keep-aliveтогда не рукопожатие
97. TCP keepAlive и HTTP keepalive
-
KeepAlive в TCP фокусируется на поддержании соединения между клиентом и сервером и время от времени отправляет пакеты пульса, чтобы проверить, не разорвано ли соединение.
-
Поддержание активности HTTP позволяет клиенту сервера поддерживать это соединение без повторного подключения с помощью tcp.
98. Может ли TCP рукопожатие дважды?
Если запрос на подключение делается в первый раз, если сервер не подтверждает, клиент делает еще один запрос, потом запускают подключение, после этого, если первый раз только затянулось, то отправляем клиенту сейчас, если нет трехэтапного рукопожатия, соединение открывается напрямую, но у клиента нет данных для передачи, сервер всегда будет ждать, пока клиент отправит данные
99. Можно ли передавать данные при трехстороннем рукопожатии TCP?
Первый и второй раз не могут быть, потому что их легко атаковать, а третье рукопожатие вошло в состояние установления, и возможности отправки и получения обеих сторон были подтверждены и могут быть переданы.
100. Состояния ожидания 2MSL
MSL — максимальное время жизни сообщения.После того, как клиент переходит в состояние timewait, ему нужно подождать 2msl, чтобы последний отправленный ack не был потерян и соединение было закрыто в обычном режиме.Time_wait — для предотвращения последнего ack повторная передача может быть потеряна.
101. websocket
HTTP-соединение является пассивным, и оно может только активно запрашивать у сервера наличие новых сообщений и продолжать опрос.
Websocket — это постоянный протокол, и он не будет автоматически отключен при подключении. А при отправке информации вам нужно всего лишь отправить небольшое сообщение кивка. Одно рукопожатие, постоянное соединение
- Сначала выполните трехстороннее рукопожатие TCP
- После успешного установления TCP-соединения браузер отправляет номер версии, адрес и другую информацию, поддерживаемую веб-сокетом, на сервер по протоколу http.
- После того, как сервер его примет, если версия протокола совпадает и формат пакета правильный, соединение принимается (Upgrade: websocket, Connection: Upgrade)
- После того, как браузер получает ответ, запускается событие onopen, и данные могут быть отправлены через send.
102. hasOwnProperty
Этот метод будет проходить только по своим собственным свойствам, а не по цепочке прототипов.Его можно использовать для определения того, относится ли свойство к объекту или унаследовано от цепочки прототипов.
const obj = new Object()
obj.num = 1
Object.prototype.fn = function(){
console.log(2)
}
obj.hasOwnProperty(num) // true
obj.hasOwnProperty(fn) // false
103. Разрешение доменного имени DNS
Процесс разрешения доменного имени
- Проверьте кеш браузера на наличие IP-адреса доменного имени.
- Проверьте, существует ли IP-адрес доменного имени в локальном кеше.
- Инициировать запрос разрешения доменных имен в локальную систему службы разрешения доменных имен (LDNS).
- Инициировать запрос разрешения доменных имен на корневой сервер разрешения доменных имен.
- Сервер корневых доменных имен возвращает адрес сервера разрешения доменных имен рДВУ.
- Инициировать запрос разрешения на сервер gTLD
- Сервер GTLD возвращает сервер Name Server
- Сервер имен возвращает IP-адрес локальному серверу
- Локальный сервер доменных имен кэширует результаты разрешения
- Возвращает результат парсинга пользователю
Разрешение доменного имени
- Запись: A представляет
address, используется для указания IP-адреса, соответствующего доменному имени - Запись MX: вы можете указать почтовый сервер под доменным именем на свой собственный почтовый сервер.
- Запись CNAME: разрешите псевдоним, укажите, что имя домена может быть разрешено в другой домен
- Запись NS: укажите конкретный DNS-сервер для разрешения доменного имени.
- Запись TXT: описание, указанное для настройки имени хоста или доменного имени.
104. Принцип JWT
использоватьJWTСерверу не нужно сохранять данные сессии, его проще расширять
структура данных
Состоит из трех частей, в середине.отдельный
- header
- payload
- signature
header
{
"alg": "HS256",
"typ": "JWT"
}
alg представляет алгоритм, type представляет тип и, наконец, преобразует его в строку с кодировкой base64.
payload
В дополнение к официально заданным полям мы также можем настроить поля, например:
{
"name": "bb",
"age" : 21
}
signature
Это подпись для предотвращения подделки предыдущих данных.
Нам нужно настроитьключ, не могут быть известны пользователю, а затем сгенерировать подпись
Как использовать и особенности
Как использовать
- После того, как клиент его получит, он может сохранить файл cookie или localStorage.
- Каждый запрос может быть добавлен в пользовательский заголовок запроса.
Authorization
Функции
- Он не зашифрован по умолчанию, вы можете зашифровать его самостоятельно через ключ
- Состояние сеанса не может быть сохранено и действует до истечения срока действия.
- Попробуйте использовать https, чтобы предотвратить утечку
105. Что такое DOCTYPE и его роль
DOCTYPE используется для объявления типа документа и спецификации DTD. В основном используется для проверки легитимности документов. Если вы хотите улучшить совместимость браузера, вам нужно установить<!DOCTYPE>
106. Принцип коа
koa разработан на основе экспресса, но он более лаконичен, имеет более высокую степень свободы и очень легковесен. Функции реализуются с помощью подключаемых модулей.Этот шаблон архитектуры подключаемых модулей соответствует философии Unix.
koa2 не использует генератор, но использует async/await
И выразить разницу
выражать:
- интегрировано больше функций
- Но функция обратного вызова очень неудобна
коа:
- Удобнее использовать async/await
- Вам необходимо настроить собственное промежуточное ПО для плагинов и т. д.
структура
application.js
Это входной файл, наследование событий может выполнять мониторинг событий и запускать события.
- listen должен инкапсулировать http.createServer и передать функцию обратного вызова, включая промежуточное ПО, контекст, разрешение и т. д.
- использовать для сбора промежуточного программного обеспечения, помещения нескольких промежуточного программного обеспечения в очередь кеша и объединения их с помощью koa-compose.
context.js
Это контекст приложения ctx koa, через который вы можете получить доступ к заголовкам запросов, установить заголовки ответов и т. д.
request/response.js
Инкапсулируйте собственные req, res и т. д., вы можете получить заголовки здесь, чтобы установить заголовки/тело и т. д.
луковая модель
app.use(async (ctx, next) => {
console.log(1);
await next();
console.log(6);
});
app.use(async (ctx, next) => {
console.log(2);
await next();
console.log(5);
});
app.use(async (ctx, next) => {
console.log(3);
ctx.body = "hello world";
console.log(4);
});
Выход 1 2 3 4 5 6
То есть сначала выполнить сверху внизawait next()предыдущий контент, а затем выполнить снизу вверхawait next()содержание после
koa помещает промежуточное ПО в очередь через функцию использования, а луковая модель позволяет выполнять все промежуточное ПО последовательно.next()Передайте параметр ctx
next()Это равносильно эстафетной палочке, передаче параметров и т.д. следующему промежуточному ПО. Просто выполните следующий, чтобы выполнить все последующие промежуточные программы!
В отличие от экспресс-фреймворка, для изменения ответа нужно дождаться завершения запроса, но с koa вы можете поместить код для изменения ответа после следующего.
Предварительная обработка -> передача и ожидание обработки другим промежуточным ПО -> постобработка
107. Основные принципы вавилона
что такое бабель
Babel — это компилятор js, который преобразует код в код, совместимый с браузерами.
- Преобразование синтаксиса
- Добавить недостающие функции через полифилл
- преобразование исходного кода js
основные принципы вавилона
Ядром является абстрактное синтаксическое дерево AST.
- Разбор: сначала преобразовать исходный код в абстрактное синтаксическое дерево, лексический анализ, синтаксический анализ
- преобразование: обработка абстрактного синтаксического дерева для создания нового синтаксического дерева.
- генерация (генерация): генерировать код js из нового синтаксического дерева
108. номер версии нпм
номер версии
Номер версии X.y.z три
- Основные изменения, обратная несовместимость, необходимо обновить X
- Добавление функций, обратная совместимость, обновление Y
- Исправить ошибки, обновить Z
определенные символы
- ~: приблизительное совпадение, фиксированные Y, Z могут быть изменены по желанию
- ^: Совместимость с определенной версией, фиксированные изменения X, Y, Z
- x: любая версия, например.
1.x.2, это может быть1.4.2,1.8.2
109. git rebase и слияние
- rebase: отменит каждую фиксацию ветки, затем обновится до последней ветки, найдет первую идентичную фиксацию в двух ветвях, а затем извлечет все записи после этого и добавит их в конец целевой ветки,
- слияние: объединить две ветки в одну ветку и отправить два коммита. Создайте новый объект фиксации, пусть предыдущие записи двух ветвей указывают на новый объект фиксации, и все предыдущие фиксации будут сохранены.
110. Принцип React-маршрутизатора
в основном зависит отhistoryбиблиотека.
Маршрутизатор верхнего уровня прослушивает историю.Когда история изменяется, маршрутизатор вызывает setState, чтобы передать местоположение вниз. Установите значение RouterContext. Маршрутизатор решает, следует ли отображать в соответствии с RouterContext.
Тег Link отключает событие по умолчанию тега a и вызывает метод history.push для изменения URL-адреса.
111. document.readyState
- загрузка: дом все еще загружается
- интерактивный: dom загружается, но изображения, css и т. д. все еще загружаются
- завершено: все загружено
112. symbol
Функция symbol возвращает значение типа symbol, которое не поддерживает new.
- Разрешение конфликтов имен свойств
- частная собственность
113. Samsite cookie
свойства файлов cookieSameSiteимеет три значения
- строгий: сторонние файлы cookie полностью запрещены, и файлы cookie не будут отправляться ни при каких обстоятельствах при межсайтовом размещении.
- нестрогий: сторонние файлы cookie запрещены в большинстве случаев, за исключением запросов на получение, которые переходят к целевому URL-адресу (например, тег, запрос предварительной загрузки, форма получения)
- нет: атрибут samesite отключен, но должен быть установлен
secureВступить в силу
114. Разница между асинхронностью и обещанием
- более лаконичный
- Вы можете использовать try/catch для обработки ошибок
- Очень удобно использовать промежуточное значение для перехода к следующему промису, не нужно держать потом как промисы
- Ошибки легко отследить, в какую строку сообщит об ошибке?
115. Как import и require реализованы в браузерах
import
Его нужно преобразовать с помощью babel и преобразовать в спецификацию commonJS.
export
Напримерexport defaultбудет преобразован вexports.default
// babel编译前
export default {}
// babel编译后
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = {};
/*
* exports
* {default: {} , __esModule: true}
*/
import
использовать_interopRequireDefaultЧтобы разобраться с этим еще раз, чтобы быть совместимым и различать commonjs и es6
// babel编译前
import Test, {msg, fn} from 'test'
// babel编译后
'use strict';
var _test = require('test');
var _test2 = _interopRequireDefault(_test);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
В вебпаке будет
importа такжеexportдобавить один__esModule: trueЛоготип, чтобы отметить это материал ES6
116. Разница между target и currentTarget
- цель: возвращает исходный объект, вызвавший событие
- currentTarget: возвращает объект, привязанный к событию.
document.getElementById('test').addEventListener('click', function (e) {
console.log(e.target)
console.log(e.currentTarget)
})
<div id="test">
<button>1</button>
</div>
117. Почему javascript однопоточный?
- Проблема предотвращения конфликтов рендеринга dom
- Веб-воркеры в html5 могут реализовать многопоточность
118. Предварительное разрешение DNS
- После загрузки исходного html-кода теги ссылок, содержащихся на странице, будут проанализированы, и соответствующее доменное имя будет запрошено заранее.
- Для посещенных страниц будет записан список доменных имен, а DNS будет разрешен одновременно с повторной загрузкой html.
预解析某域名
<link rel="dns-prefetch" href="//img.alicdn.com">
强制开启HTTPS下的DNS预解析
<meta http-equiv="x-dns-prefetch-control" content="on">
119. Что такое пучок, чанк, модуль
- Bundle относится к файлам, упакованным webpack.
- Чанк относится к блоку кода, разделенному кодом, когда веб-пакет выполняет анализ зависимостей модулей.
- модуль - это отдельный модуль в разработке
120. Что такое загрузчик и плагин
- Загрузчик — это способность веб-пакета загружать и анализировать файлы, отличные от js.
- Плагины могут расширить функциональность веб-пакета и сделать его более гибким.
121. Принцип ленивой загрузки компонентов
- Например
react-loadableосновное использованиеimport()Чтобы вернуть характер обещания выполнять асинхронные операции загрузки. - веб-пакет через
require.ensure()Для достижения загрузки по требованию
require.ensure
require.ensure(dependencies,callback,errorCallback,chunkName)он вернетpromise, первый судьяdependenciesНезависимо от того, было ли оно загружено, кэшированное значение получается после загрузки. Если нет, создайте одинpromise, а затем кэшировать его. Затем создайтеscriptтег, заполните информацию и поместите ее в html-файл, и загрузка по запросу завершена.
require.ensure может настроить имя файла
122. Автономный кэш HTML5
использоватьmanifestатрибут, когда браузер обнаруживает, что заголовок имеетmanifestатрибут, будет запрошен файл манифеста, и если это первый раз, соответствующие ресурсы будут загружены в соответствии с содержимым файла. Если он был кэширован в автономном режиме, он будет напрямую использовать автономную загрузку ресурсов.
123. Как предотвратить кликджекинг
Злоумышленник устанавливает прозрачность iframe, вставляя iframe, чтобы побудить пользователя щелкнуть.
Можно установить через заголовки httpX-FRAME-OPTIONSДля защиты от атак кликджекинга, вложенных в iframe
124. Шаблон наблюдателя и шаблон публикации-подписки
Шаблон наблюдателя
function Subject() {
this.state = 0
this.observers = []
}
Subject.prototype.attach = function (observer) {
this.observers.push(observer)
}
Subject.prototype.getState = function () {
return this.state
}
Subject.prototype.setState = function (state) {
this.state = state
this.noticefyAllObservers()
}
Subject.prototype.noticefyAllObservers = function () {
this.observers.forEach(observer => {
observer.update()
})
}
function Observer(name, subject) {
this.name = name
this.subject = subject
this.subject.attach(this)
}
Observer.prototype.update = function () {
console.log(this.name, this.subject.getState())
}
const subject = new Subject()
const o1 = new Observer('o1', subject)
const o2 = new Observer('o2', subject)
const o3 = new Observer('o3', subject)
subject.setState(1)
subject.setState(2)
subject.setState(3)
модель публикации-подписки
function Event() {
this.events = {}
}
Event.prototype.on = function (event, fn) {
if (!this.events[event]) {
this.events[event] = []
}
this.events[event].push(fn)
}
Event.prototype.emit = function (event) {
const args = [...arguments].splice(1)
this.events[event].forEach(fn => {
fn.apply(this, args)
})
}
Event.prototype.off = function (event, fn) {
const currentEvent = this.events[event]
this.events[event] = currentEvent.filter(item => item !== fn)
}
const publisher = new Event()
const fn1 = function (e) {
console.log('a1')
console.log(e)
}
const fn2 = function (e) {
console.log('a2')
console.log(e)
}
publisher.on('a', fn1)
publisher.on('a', fn2)
publisher.emit('a', 'aowu')
publisher.off('a', fn2)
publisher.emit('a', 'aowu')
разница
- В режиме наблюдателя наблюдатель знает субъекта, а в режиме публикации-подписки издатель и подписчик не знают о существовании друг друга и общаются только через брокера сообщений.
- Шаблон наблюдателя в основном синхронный, а публикация и подписка в основном асинхронные.
- Большая часть режима подписки на выпуск является слабосвязанной, наблюдатель
128. Балансировка нагрузки nginx
блог woo woo woo.cn на.com/alter em/afraid/1… woo woo Краткое описание.com/afraid/4 из 250 из 1 Чэнду…
129. redis
130. Set,Map,WeakSet,WeakMap
- Set: можно пройти, элемент уникален
- WeakSet: все элементы являются объектами, а все элементы являются слабыми ссылками, которые могут быть удалены сборщиком мусора, не так легко вызвать утечку памяти и не могут быть пройдены.
- Карта: пары ключ-значение, по которым можно пройти
- WeakMap: имя ключа — это объект, а имя ключа — это слабая ссылка, которую нельзя пройти.
131. Разница между токеном и куки
token
- Шифрование и дешифрование занимает много времени и занимает много памяти
- Поддерживает не только браузеры, но и мобильные терминалы и т. д.
- Может предотвратить атаки crsf
- Токены не имеют состояния и хорошо масштабируются
cookie
- Автоматически отправлять, удобно
- Не могу использовать файлы cookie на стороне приложения
- Неиспользование в https уязвимо для атаки crsf
132. нулевой и неопределенный
- null: тип объекта, конечная точка цепочки прототипов объектов, определенная, является нулевым значением
- undefined: означает отсутствие присвоения, неопределенный тип, неопределенный
133. Используйте persist в реакции
После вызова синтетического события реакции все это будет использовано повторно, и все свойства будут недействительными.Если вы хотите получить к нему доступ асинхронно, вы должны использоватьevent.persist(), который будет удален из пула событий, что позволит сохранить ссылку на событие
134. position: relative повлияет на такие свойства, как offsetLeft дочерних элементов.
135. В чем разница между мини-программами и H5
- Метод рендеринга апплета отличается от метода H5. Апплет обычно визуализируется Native, но апплет также поддерживает веб-рендеринг. Вы можете инициализировать компонент веб-просмотра и загрузить страницу H5 в веб-просмотре.
Под апплетом нативный режим имеет лучшую производительность, чем веб-режим
- Небольшой двухпоточный дизайн для конкретной программы. Под H5 мы обычно упаковываем все в один файл. После компиляции апплета остается два, а именно слой представления и бизнес-логика. При запуске будет два потока, обрабатывающих два файла соответственно, один из которых является основным потоком рендеринга, который отвечает за рендеринг содержимого слоя представления. Другой поток — рабочий поток службы, который отвечает за выполнение бизнес-логики.
- В зависимости от операционной среды h5 в основном используется в веб-просмотре или браузерах.Апплет использует встроенный парсер, основанный на рефакторинге браузера, что значительно оптимизирует производительность, кеширование и т.д.
- Производительность отличается.Апплет использует клиент WeChat для реализации множества оптимизаций для синтаксического анализа.При первом открытии много ресурсов будет кэшироваться, поэтому он намного более плавный, чем H5.Основная технология оптимизации делает апплет ближе к родному APP.
- Стоимость разработки мини программы низкая, не нужно беспокоиться о необъяснимых багах, вы можете позвонить в официальный апи
- Больше пользователей WeChat, больше трафика WeChat, чем у h5
- апплет не может использовать dom
- Апплет может использовать разрешения многих мобильных телефонов.
136. Срез строки, подстрока, подстрока
- Ломтик: нормальный перехват, если есть отрицательное число, оно будет подсчитано назад
- substr: первый параметр — это начальный индекс, а второй параметр указывает, сколько символов нужно перехватить.
- подстрока: передать два параметра, меньший из которых является начальным индексом
137. Основные виды упаковки
Примитивные типы не являются объектами, но у них есть какие-то методы, почему?
Поскольку фон будет обертывать основные типы, такие как строки, целые числа и логические значения, конструктор будет использоваться для создания экземпляра в первую очередь, и он будет уничтожен после использования.
let s1 = 'hello'
let s2 = s1.substring(2)
// ↓ 后台包装
let s1 = new String('hello') // 包装
let s2 = s1.substring(2) // 可以调用方法
s1 = null // 销毁
138. toString и valueOf
- Нет методов для null и undefined
- toString: тип значения возвращает форму строки, а тип объекта возвращает форму [объект объекта].
- valueOf: независимо от того, является ли это значением или ссылочным типом, он в основном возвращается как есть.Когда это дата, возвращается метка времени.
- При преобразовании строк предпочтительнее использовать toString, а для числовых расчетов — valueOf.
- Параметр поддержки TOSTRING, вы можете конвертировать Hex
139. Класс es6 реализует приватные переменные
- Закрытие
class A {
constructor (x) {
let _x = x
this.showX = function () {
return _x
}
}
}
let a = new A(1)
// 无法访问
a._x // undefined
// 可以访问
a.showX() // 1
- использовать символ
class A {
constructor(x) {
// 定义symbol
const _x = Symbol('x')
// 利用symbol声明私有变量
this[_x] = x
}
showX() {
return this[_x]
}
}
let a = new A(1)
// 1. 第一种方式
a[_x] // 报错 Uncaught ReferenceError: _x is not defined
// 2. 第二种方式
// 自行定义一个相同的Symbol
const x = Symbol('x')
a[x] // 无法访问,undefined
// 3. 第三种方式,可以访问(正解)
a.showX() //1
140. Тип и интерфейс TypeScript
interface
- то же имя
interfaceАвтоматическая агрегация, также может быть с тем же именемclassАвтоматическая агрегация - может означать только
object,function,classТипы
type
- не только выразить
object,function,classТипы - Не может быть одного и того же имени
- Поддержка операций со сложными типами
141. Движок V8 для JavaScript
JavaScript-движок
JavaScript — это解释型язык, с编译型Разные языки, при парсинге выполняется js. Для повышения производительности были введены некоторые фишки виртуальной машины Java и компилятора C++.
Процесс реализации
исходный код -> абстрактное синтаксическое дерево -> байт-код -> JIT -> собственный код
двигатель V8
По сравнению с другими движками javascript (преобразованными в байт-код или интерпретированными и выполненными), движок V8 компилирует код непосредственно в собственный машинный код и использует встроенное кэширование для повышения производительности.
Рабочий процесс: исходный код сначала анализируется в абстрактное синтаксическое дерево, а затем JIT-компилятор используется для генерации кода непосредственно из абстрактного синтаксического дерева для повышения скорости выполнения кода (не нужно ли его преобразовывать в байты)
142. Разница между кучей и стеком
- Куча: в основном хранит блоки памяти, выделенные новыми и т. д., компилятор не освобождает их автоматически, а ссылочные типы помещаются в кучу
- Стек: в основном хранятся параметры функций, локальные переменные и т. д., компилятор автоматически выделяет и освобождает, а основные типы данных помещаются в стек.
143. unicode utf8 utf16
- Юникод предназначен для решения проблемы неравномерного кодирования в мире.Он содержит набор кодировок всех символов и символов.Каждый символ представлен 2 байтами.Английским символам нужен только 1 байт, поэтому экономия места будет напрасной тратой места.
- UTF8 передает 8 битов за раз, что является методом кодирования переменной длины. Он использует от 1 до 4 байта для представления символа, а китайские символы UTF8 обычно используют 3 байта.
- utf16 передает 16 бит за раз
разница
unicode: набор кодировок для всех символов в мире utf8, utf16: набор символов Unicode, различные реализации кодировки
144. Разница между классом и функцией
- Инкапсуляция классов более разумна, проста в обслуживании и использовании.
- класс не имеет повышения состояния, как функция
- Классам удобнее не писать методы-прототипы
- Чтобы использовать суперкласс, чтобы использовать это