Основные навыки фронтенд-интервью

интервью

Самое полное руководство по фронтенд-интервью в 2020 году, с более чем месячным опытом собеседований, накопленным 1,8w слов, и, наконец, успешно вошедшим с ним в большую фабрику ...

В этом году золотая тройка, серебряная четверка только что настигла эпидемию, многие крупные компании прекратили набор или даже увольнения, а мелкие партнеры, желающие сменить работу, застигнуты врасплох.

Спрос будет снижен, а требования определенно возрастут.Я хотел бы посвятить это писание вам, кто смел и силен в такие трудные времена~

больше подходит для интервьюНеобходимые навыки для фронтенд-интервью (2) Разбор сложных моментовГотово, две статьи объединены, чтобы выглядеть лучше~

最近掘金有点不稳定,文章偶尔看不到,没有删除,过会儿再看看有没有……

предисловие

Сложность и глубина вопросов, заданных в этом году, должны быть увеличены по сравнению с предыдущими годами.Ниже приводится анализ двух аспектов общего анализа и важных моментов:

Общий анализ

  • Интерфейс больше всего спрашивает о фундаменте js, фундаменте компьютерной сети и т. Д. Здесь рекомендуется приложить больше усилий.
  • И вопросы, связанные с css, задают редко.В лучшем случае они спрашивают о макете в три столбца, макете в два столбца, горизонтальном и вертикальном центрировании.После прочтения первых двух разделов интервью проблем в принципе не возникает.
  • Вопросы, связанные с Framework React/Vue, чаще задают в малых и средних компаниях, что составляет почти половину времени собеседования. А большие фабрики не любят спрашивать о фреймворках, и больше внимания уделяют основам, потому что после поступления на работу ты можешь использовать тот фреймворк, который хочешь использовать... Даже если ты спрашиваешь, ты спрашиваешь об относительно низких -уровневые вещи, такие как принцип двусторонней привязки Vue.

важная точка

Напоследок перечислю несколько важных моментов, которые в основном задают большие, средние или малые компании:

  • Оптимизация производительности, и как сделать каждую точку оптимизации, каждая точка может быть расширена.
    • Например, если вы говорите об асинхронной загрузке, интервьюер спросит о методе асинхронной загрузки, о разнице между отложенной и асинхронной загрузкой.
    • Вы сказали, чтобы полностью использовать кеш, интервьюер спросит, каковы методы кеша, что такое сильный кеш, что такое согласованный кеш, каковы их коды возврата, какие ресурсы существуют в кеше памяти и какие существуют в кеше диска...
  • http/https/http2.0. Три рукопожатия и четыре волны, почему https медленнее в плане безопасности, чем отличается от http, какие есть оптимизации http2.0, весь процесс от ввода браузером URL до просмотра страницы...
  • Для распространенных атак безопасности помните принципы и превентивные меры атак CSRF и XSS.
  • Новые возможности ES6 и различные извращения для var и let.
  • Несколько способов пересечения доменов.


В дополнение к вышесказанному, крупные компании также любят предлагать вам проект, который вы считаете лучше, и какие у него есть основные моменты. Эта часть должна быть хорошо подготовлена, лучше всего очень глубоко понимать технологию, используемую в проекте, о котором вы говорите, чтобы не копать себе ямы.

В этой статье много контента, а упрощенная и целенаправленная версия будет опубликована позже для удобства просмотра, так что следите за обновлениями~

1. Макет страницы

Макет с тремя колонками

Вопрос: Предполагая, что высота известна, пожалуйста, напишите макет из трех столбцов, в котором левый и правый столбцы имеют ширину по 300 пикселей, а средний — адаптивный.
Ответ: Методов компоновки может быть много, вот пять типов: плавающая компоновка, абсолютная компоновка, гибкая компоновка, табличная компоновка, сетка, код такой:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>三栏布局</title>
	<link rel="stylesheet" href="">
	<style type="text/css" media="screen">
		html *{
			margin: 0;
			padding: 0;
		}
	</style>
</head>
<body>
	<section class="layout float">
		<style type="text/css" media="screen">
			.layout.float .wrapper>div{
				min-height: 100px;
			}
			.layout.float .left{
				float: left;
				width: 300px;
				background: red;
			}
			.layout.float .center{
				background: yellow;
			}
			.layout.float .right{
				float: right;
				width: 300px;
				background: blue;
			}
			
		</style>
		<article class="wrapper">
			<div class="left"></div>
			<div class="right"></div>
			<div class="center">
				<h1>float布局</h1>
				1.我是float布局的中间部分
				2.我是float布局的中间部分
			</div>
		</article>
	</section>


	<section class="layout absolute">
		<style type="text/css" media="screen">
			.layout.absolute .wrapper{
				width: 100%;
				margin-top: 20px;
			}
			.layout.absolute .wrapper>div{
				min-height: 100px;
			}
			.layout.absolute .left{
				position: absolute;
				left: 0;
				width: 300px;
				background: red;
			}
			.layout.absolute .center{
				position: absolute;
				left: 300px;
				right: 300px;
				background: yellow;
			}
			.layout.absolute .right{
				position: absolute;
				right: 0;
				width: 300px;
				background: blue;
			}
		</style>
		<article class="wrapper">
			<div class="left"></div>
			<div class="center">
				<h1>absolute布局</h1>
				1.我是absolute布局的中间部分
				2.我是absolute布局的中间部分
			</div>
			<div class="right"></div>
		</article>
	</section>


	<section class="layout flex">
		<style type="text/css" media="screen">
			.layout.flex .wrapper{
				width: 100%;
				min-height: 100px;
				display: flex;
				margin-top: 140px;
			}
			.layout.flex .left{
				width: 300px;
				background: red;
			}
			.layout.flex .center{
				flex: 1;
				background: yellow;
			}
			.layout.flex .right{
				width: 300px;
				background: blue;
			}
		</style>
		<article class="wrapper">
			<div class="left"></div>
			<div class="center">
				<h1>flex布局</h1>
				1.我是flex布局的中间部分
				2.我是flex布局的中间部分
			</div>
			<div class="right"></div>
		</article>
	</section>


	<section class="layout table">
		<style type="text/css" media="screen">
			.layout.table .wrapper{
				display: table;
				width: 100%;
				min-height: 100px;
				margin-top: 20px;
			}
			.layout.table .left{
				display: table-cell;
				width: 300px;
				background: red;
			}
			.layout.table .center{
				display: table-cell;
				background: yellow;
			}
			.layout.table .right{
				display: table-cell;
				width: 300px;
				background: blue;
			}
			
		</style>
		<article class="wrapper">
			<div class="left"></div>
			<div class="center">
				<h1>table布局</h1>
				1.我是table布局的中间部分
				2.我是table布局的中间部分
			</div>
			<div class="right"></div>
		</article>
	</section>


	<section class="layout grid">
		<style type="text/css" media="screen">
			.layout.grid .wrapper{
				display: grid;
				grid-template-columns: 300px auto 300px;
				grid-template-rows: 100px;
				width: 100%;
				margin-top: 20px;
			}
			.layout.grid .left{
				background: red;
			}
			.layout.grid .center{
				background: yellow;
			}
			.layout.grid .right{
				background: blue;
			}
			
		</style>
		<article class="wrapper">
			<div class="left"></div>
			<div class="center">
				<h1>grid布局</h1>
				1.我是grid布局的中间部分
				2.我是grid布局的中间部分
			</div>
			<div class="right"></div>
		</article>
	</section>
</body>
</html>


Во время интервью напишите не менее трех из них.
Есть три возможных направления развития следующей проблемы:

  1. Каковы плюсы и минусы каждого варианта?
  2. Если высота не фиксирована, какая из них обычно используется на практике?
  3. Насколько совместимы вышеуказанные решения?

Плюсы и минусы каждого макета

1. Плавающая компоновка

Преимущества: Проще и лучше совместимость. Пока очистка поплавка выполнена хорошо, проблем нет.
Недостатки: Плавающие элементы отделены от потока документа, чтобы очистить флот, если с этим не обращаться должным образом, это принесет много проблем, таких как коллапс высоты.

2. Абсолютный макет

Достоинства: очень быстро, легко настраивается, не вызывает проблем
Недостатки: Абсолютное позиционирование находится вне документооборота, а значит, все подэлементы ниже тоже будут вне документооборота, что приводит к низкой эффективности и удобству использования этого метода.

3. гибкий макет

Плюсы: Просто и быстро
Недостаток: не поддерживает IE8 и ниже.

4. макет таблицы

Преимущества: простота реализации, меньше кода
Недостатки: Когда одна из ячеек превышает высоту, ячейки с обеих сторон также становятся выше, и иногда этот эффект не то, что нам нужно.

5. макет сетки

Похож на флекс.

Центрируется по горизонтали и вертикали

абсолютная + отрицательная маржа

Этот способ прост для понимания и имеет хорошую совместимость, недостаток в том, что нужно знать ширину и высоту дочерних элементов.

<div class="out">
  <div class="inner">12345</div>
</div>

<style type="text/css">
  .out{
    position: relative;
    width: 300px;
    height: 300px;
    background: red;
  }

  .inner{
    position: absolute;
    width: 100px;
    height: 100px;
    background: yellow;
    left: 50%;
    top: 50%;
    margin-left: -50px;
    margin-top: -50px;
  }
</style>

absolute + auto margin

Этот метод также очень совместим, недостаток в том, что вам нужно знать ширину и высоту дочерних элементов.

<style type="text/css">
  .out{
    position: relative;
    width: 300px;
    height: 300px;
    background: red;
  }

  .inner{
    position: absolute;
    width: 100px;
    height: 100px;
    background: yellow;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
  }
</style>

absolute + calc

Совместимость этого метода зависит от calc, а также необходимо знать ширину и высоту

<style type="text/css">
  .out{
    position: relative;
    width: 300px;
    height: 300px;
    background: red;
  }

  .inner{
    position: absolute;
    width: 100px;
    height: 100px;
    background: yellow;
    left: calc(50% - 50px);
    top: calc(50% - 50px);
  }
</style>

absolute + transform

Совместимость зависит от перевода, не нужно знать ширину и высоту дочерних элементов.

<style type="text/css">
  .out{
    position: relative;
    width: 300px;
    height: 300px;
    background: red;
  }

  .inner{
    position: absolute;
    background: yellow;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
</style>

table

Новый атрибут таблицы css позволяет нам превращать обычные элементы в эффект отображения элементов таблицы. Благодаря этой функции мы также можем добиться горизонтального и вертикального центрирования.
Этот метод также совместим.

<style type="text/css">
  .out{
    display: table-cell;
    width: 300px;
    height: 300px;
    text-align: center;
    vertical-align: middle;
    background: red;
  }

  .inner{
    display: inline-block;
    background: yellow;
    width: 100px;
    height: 100px;
  }
</style>

flex

Flex относительно прост в реализации, и это можно сделать с помощью трех строк кода. Выравнивание дочерних элементов может быть задано родительским элементом или выравнивание дочерних элементов может быть задано ими самими. Для второго способа см. макет сетки.

<style type="text/css">
  .out{
    display: flex;
    justify-content: center;
    align-items: center;
    width: 300px;
    height: 300px;
    background: red;
  }

  .inner{
    background: yellow;
    width: 100px;
    height: 100px;
  }
</style>

grid

Макет Grid также очень мощный, в целом свойства аналогичны flex.

//方法一:父元素指定子元素的对齐方式
<style type="text/css">
  .out{
    display: grid;
    align-content: center;
    justify-content: center;
    width: 300px;
    height: 300px;
    background: red;
  }

  .inner{
    background: yellow;
    width: 100px;
    height: 100px;
  }
</style>

//方法二:子元素自己指定自己的对齐方式
<style type="text/css">
  .out{
    display: grid;
    width: 300px;
    height: 300px;
    background: red;
  }

  .inner{
    background: yellow;
    width: 100px;
    height: 100px;
    align-self: center;
    justify-self: center;
  }
</style>


Резюме макета страницы:

  • Семантика на месте
  • Глубокое понимание макета страницы
  • Твердые основы CSS
  • Гибкий и инициативный
  • Спецификация написания кода

Блочная модель CSS

Блочная модель CSS является краеугольным камнем внешнего интерфейса. Этот вопрос варьируется от мелкого к более глубокому, от простого к сложному. Вы можете задать следующие вопросы по очереди.

  • Основная концепция: стандартная модель + модель IE
  • Разница между стандартной моделью и моделью IE
  • Как CSS настраивает эти две модели
  • Как JS устанавливает и получает ширину и высоту, соответствующие блочной модели
  • Пример вопроса (объясните перекрывающиеся поля в соответствии с блочной моделью)
  • BFC (решение перекрытия маржи)

1. Основные понятия

Все HTML-элементы можно рассматривать как блоки.В CSS термин «блочная модель» используется для дизайна и компоновки.
Блочная модель CSS — это, по сути, блок, который инкапсулирует окружающие элементы HTML, включая: поля, границы, отступы и фактическое содержимое.
Блочная модель позволяет размещать элементы в пространстве между другими элементами и границами окружающих элементов.
На следующем рисунке показана блочная модель:
image.png

2. Разница между стандартной моделью и моделью IE

Разница между стандартной моделью и моделью IE заключается в том, что ширина и высота рассчитываются по-разному.
Стандартная модель вычисляет ширину и высоту элемента только по ширине и высоте содержимого, а модель IE — это общий размер содержимого + отступы + граница.
Если ширина и высота содержимого равны 100100px, padding 10px, border 10px, margin 10px, тогда в стандартной модели ширина этого элемента 100px и высота 100px.
В модели IE ширина 100px + 2.
10px (левое и правое отступы) + 210 пикселей (левая и правая границы) = 140 пикселей;
Высота 100px + 2
10px (верхний и нижний отступы) + 2*10px (верхняя и нижняя граница) = 140px;
image.png
image.png

3. Как настроить эти две модели

//设置标准模型
box-sizing: content-box;
//设置IE模型
box-sizing: border-box;

Значение по умолчанию box-sizing — это content-box, что является стандартной моделью по умолчанию.

4. Как задать ширину и высоту блочной модели в JS

Предположим, что полученный узелdom 

//只能获取内联样式设置的宽高
dom.style.width/height

//获取渲染后即时运行的宽高,值是准确的。但只支持 IE
dom.currentStyle.width/height

//获取渲染后即时运行的宽高,值是准确的。兼容性更好
window.getComputedStyle(dom).width/height;

//获取渲染后即时运行的宽高,值是准确的。兼容性也很好,一般用来获取元素的绝对位置,getBoundingClientRect()会得到4个值:left, top, width, height
dom.getBoundingClientRect().width/height;

5. БФК

Что такое БФК? Контекст форматирования блока.
Прежде чем объяснять, что такое BFC, нам нужно знать концепции Box и Formatting Context.

Box: основная единица макета css

Блок — это объект и основная единица макета CSS.Интуитивно говоря, страница состоит из множества блоков. Тип элемента и свойство display определяют тип Box. Различные типы блоков будут участвовать в разных контекстах форматирования (контейнер, который определяет, как отображать документ), поэтому элементы внутри блока будут отображаться по-разному. Посмотрим, какие коробки есть:

  • Блок блочного уровня: Элемент, чей атрибут display имеет значение block, list-item, table, создаст блок блочного уровня. И участвовать в блоке форматирования контекста;
  • блок встроенного уровня: элемент, свойство отображения которого является встроенным, встроенным блоком или встроенной таблицей, создаст блок встроенного уровня. И участвовать во встроенном контексте форматирования;
  • окно запуска: доступно только в css3, поэтому я не буду говорить об этом здесь.

Formatting Context

Контекст форматирования — это понятие в спецификации W3C CSS2.1. Это область рендеринга на странице и имеет набор правил рендеринга, которые определяют, как будут расположены его дочерние элементы и как они будут связаны и взаимодействовать с другими элементами. Наиболее распространенные контексты форматирования:Block fomatting context(сокращенно BFC) иInline formatting context(сокращенно МФЦ).

Правила компоновки для BFC

  • Внутренние коробки будут размещены одна за другой в вертикальном направлении.
  • Вертикальное расстояние Box определяется полем. Поля двух соседних блоков, принадлежащих одному и тому же BFC, будут перекрываться.
  • Левая сторона поля поля каждого поля (блоков и строк) касается левой стороны поля границы содержащего блока (для форматирования слева направо, в противном случае наоборот). Это верно, даже если есть поплавки.
  • Область BFC не будет перекрывать флоат-бокс.
  • BFC — это изолированный и независимый контейнер на странице, и дочерние элементы внутри контейнера не будут влиять на внешние элементы. И наоборот.
  • При расчете высоты БФК в расчете также участвуют плавающие элементы.

Как создать БФЦ

  1. Значение float не равно none.
  2. Значение position не является статическим или относительным.
  3. Значение переполнения не видно.
  4. Значение display — встроенный блок, ячейка таблицы, flex, table-caption или встроенный flex.

Роль БФК

  1. Используйте BFC, чтобы избежать перекрытия полей
  2. Адаптивный двухколоночный макет
  3. очистить поплавок

3. События ДОМ

3.1 Уровень события

Три уровня событий, обратите внимание, что нет DOM1, потому что события DOM не были задействованы при формулировании стандарта DOM1. DOM3 просто добавляет некоторые типы событий поверх DOM2.

  • DOM0: element.onclick = функция () {}
  • DOM2: element.addEventListener('щелчок', function(){}, false)
  • DOM3: element.addEventListener('keyup', function(){}, false)

### 3.2 Модель событий и поток событий Модель событий DOM включает захват и всплытие.
Поток событий относится к потоку событий в процессе взаимодействия пользователя с интерфейсом.

3.3 Конкретный процесс захвата событий DOM

Захваченный процесс: окно -> документ -> html -> тело -> ... -> целевой элемент.
Процесс всплытия: целевой элемент -> ... -> тело -> html -> документ -> окно.

3.4 Общие применения объектов Event

  1. event. preventDefault()

Действие по умолчанию для отмены события.

  1. event.stopPropagation()

Остановите событие от всплытия.

  1. event.stopImmediatePropagation()

Предотвращает выполнение остальных обработчиков событий. Если к элементу привязаны три события и для одного из них вызывается этот метод, два других события выполняться не будут.

3.5 Процесс захвата события и пример пользовательского события

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>dom事件</title>
	<link rel="stylesheet" href="">
</head>
<body>
	<style type="text/css" media="screen">
		#wrapper {
			width: 300px;
			height: 150px;
			background: yellow;
		}
	</style>

	<div id="wrapper">点我啊点我啊</div>

	<script type="text/javascript">
		var eve = document.getElementById('wrapper');

		//验证事件捕获过程
		window.addEventListener('click', function(){
			console.log('window capture')
		}, true)

		document.addEventListener('click', function(){
			console.log('document capture')
		}, true)	

		//document.documentElement 获取的是 html 标签
		document.documentElement.addEventListener('click', function(){
			console.log('html capture')
		}, true)

		document.body.addEventListener('click', function(){
			console.log('body capture')
		}, true)

		eve.addEventListener('click', function(){
			console.log('eve capture')
		}, true)

		//自定义事件
		var customEvent = new Event('test')
		eve.addEventListener('test', function(){
				console.log('自定义事件 test 触发')
		}, true)

		setTimeout(() => {
			eve.dispatchEvent(customEvent)
		}, 3000)
	</script>
</body>
</html>

Результат, напечатанный в консоли:

window capture
document capture
html capture
body capture
eve capture

Это доказывает, что процесс захвата события: окно -> документ -> html -> тело -> ... -> целевой элемент.
Пользовательское событие запускается через 3 секунды, обновляет страницу, и через 3 секунды консоль выводит сообщение.自定义事件 test 触发.

4. HTTP-протокол

4.1 Основные возможности протокола http

Простой, быстрый, гибкий, без подключения, без сохранения состояния
Три вещи, которые следует учитывать при работе с HTTP:

  • HTTP не требует установления соединения: смысл без установления соединения заключается в том, чтобы ограничить обработку только одним запросом на соединение. После того, как сервер обработает запрос клиента и получит ответ клиента, он отключится. Таким образом можно сэкономить время передачи.
  • HTTP не зависит от среды: это означает, что любой тип данных может быть отправлен по HTTP, если клиент и сервер знают, что делать с содержимым данных. Клиент и сервер указывают соответствующий тип контента MIME-типа.
  • HTTP не имеет состояния: протокол HTTP не имеет состояния. Без сохранения состояния означает, что протокол не имеет памяти для обработки транзакций. Отсутствие состояния означает, что если предыдущая информация требуется для последующей обработки, она должна быть передана повторно, что может привести к увеличению объема данных, передаваемых за соединение. С другой стороны, сервер быстрее отвечает, когда ему не нужна предыдущая информация.

4.2 Сообщение запроса

Сообщение HTTP-запроса состоит из четырех частей: строки запроса, заголовка запроса, пустой строки и данных запроса.На следующем рисунке показан общий формат сообщения запроса.

  • строка запроса: Включите поле метода запроса, поле URL и версию протокола HTTP, например: GET /index.html HTTP/1.1.
  • заголовок запроса

Заголовок запроса состоит из пар ключевое слово/значение, по одной паре в строке, а ключевое слово и значение разделяются английским двоеточием ":". Заголовки запроса информируют сервер о клиентском запросе. Типичные заголовки запроса:

  • User-Agent: тип браузера, выполнившего запрос.
  • Принять: список типов контента, распознаваемых клиентом.
  • Хост: запрошенное имя хоста, несколько доменных имен могут использовать один и тот же IP-адрес, то есть виртуальный хост.
  • Content-Type: MIME-тип тела запроса (используется в запросах POST и PUT). Например: Content-Type: application/x-www-form-urlencoded
  • пустая строка

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

  • запросить данные

Данные запроса используются не в методе GET, а в методе POST. Метод POST подходит для ситуаций, когда от клиента требуется заполнить форму. Наиболее часто используемые заголовки запроса, связанные с данными запроса, — это Content-Type и Content-Length.

4.3 Ответное сообщение

В том числе: строка состояния, заголовок ответа, пустая строка, тело ответа.

4.4 Код состояния HTTP

Код состояния HTTP на английском языке — это код состояния HTTP. Код состояния состоит из трех цифр, первая цифра определяет категорию ответа, и есть пять возможных значений.

  • 1xx: Индикационная информация — указывает, что запрос получен и обработка продолжается.
  • 2xx: Успех. Указывает, что запрос был успешно получен, понят и принят.
  • 3xx: перенаправление. Для выполнения запроса необходимо предпринять дополнительные действия.
  • 4xx: Ошибка клиента — запрос содержит синтаксическую ошибку или запрос не может быть выполнен.
  • 5xx: Ошибка на стороне сервера — серверу не удалось выполнить допустимый запрос.


Ниже приведены описания общих кодов состояния и описания состояний.

  • 200 OK: запрос клиента выполнен успешно.
  • 400 Bad Request: запрос клиента содержит синтаксическую ошибку и не может быть понят сервером.
  • 401 Unauthorized: запрос не авторизован. Этот код состояния ДОЛЖЕН использоваться вместе с полем заголовка WWW-Authenticate.
  • 403 Forbidden: сервер получил запрос, но отказался его обслуживать.
  • 404 Not Found: запрошенный ресурс не существует, например: был введен неправильный URL.
  • 500 Внутренняя ошибка сервера: на сервере произошла непредвиденная ошибка.
  • 503 Сервер недоступен: сервер в настоящее время не может обработать запрос клиента и может вернуться в нормальное состояние через некоторое время, например: HTTP/1.1 200 OK (CRLF).

4.5 Оптимизация

Предварительное разрешение DNS

<!--在head标签中,越早越好-->
<link rel="dns-prefetch" href="//example.com">


предварительное подключение HTTP

<link rel="preconnect" href="//example.com">
<link rel="preconnect" href="//cdn.example.com" crossorigin>

4.6 Что происходит после того, как браузер вводит URL-адрес

В интернете много ответов, а единого стандартного ответа нет.Просто прочитайте еще несколько и расскажите общий процесс.

5. Цепочка прототипов

5.1 Несколько способов создания объектов

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>原型链</title>
	<link rel="stylesheet" href="">
</head>
<body>
	<script type="text/javascript" charset="utf-8">
		//创建对象的几种方式
		//1.字面量
		var obj1 = {name: 'solo obj1'};
		//2.new Object
		var obj2 = new Object({name: 'solo obj2'})
		//3.构造函数创建
		var M = function(name){
			this.name = name;
		}
		var obj3 = new M('solo obj3');
		//4.Object.create
		var p = {name: 'p'};
		var obj4 = Object.create(p);

	</script>
</body>
</html>


Затем просмотрите значение каждого объекта в консоли.
image.png

5.2 Прототипы, конструкторы, экземпляры, цепочки прототипов

Связь между конструктором, объектом-прототипом и экземпляром можно проследить на следующем рисунке:

image.png


В сочетании с напечатанными значениями консоли в предыдущем разделе можно сделать вывод, что:

  • конструктор.прототип.конструктор === конструктор

M.prototype.constructor === M верно

  • конструктор.прототип === объект экземпляра.proto

M.prototype === obj3._ proto_ приводит к истинному

5.3 Принцип instanceof

instanceof используется для определения того, принадлежит ли ссылочный тип конструктору; его также можно использовать для определения того, принадлежит ли экземпляр своему родительскому типу в отношении наследования.
Принцип instanceof состоит в том, чтобы судить об объекте экземпляра__proto__Это то же самое, что и конструктор?prototypeуказывает на ту же ссылку.
image.png

Instaceof будет возвращать true, пока конструктор находится в цепочке прототипов объекта экземпляра. Посмотрите на картинку ниже:
obj3 является экземпляром M, поэтомуobj3 instanceof M = true ;
в то же время obj3 instanceof ObjectРезультат также верен, потому что

obj3.__proto__ === M.prototype
true
M.prototype.__proto__ === Object.prototype
true

   
image.png

Если вы хотите точно определить, какая функция конструктора, вы можете использовать конструктор

obj3.__proto__.constructor === M
true

obj3.__proto__.constructor === Object
false

5.4 Разница между instanceof и typeof

typeof возвращает правильный тип для примитивных типов данных (null, undefined, string, number, boolean, symbol), кроме null. null возвращает объект.
typeof Для типов объектов, кроме функций, которые возвращают функцию, все остальные возвращают объект.
Если мы хотим получить правильный тип переменной, мы можем передатьObject.prototype.toString.call(xx). Таким образом, мы можем получить что-то вроде[object Type] Нить.
Метод, чтобы определить, равно ли оно undefined:

let a
// 我们也可以这样判断 undefined
a === undefined
// 但是 undefined 不是保留字,能够在低版本浏览器被赋值
let undefined = 1
// 这样判断就会出错
// 所以可以用下面的方式来判断,并且代码量更少
// 因为 void 后面随便跟上一个组成表达式
// 返回就是 undefined
a === void 0

5.5 Новый оператор

Реализовать новый метод в коде

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>模拟new的过程</title>
	<link rel="stylesheet" href="">
</head>
<body>
	<script type="text/javascript" charset="utf-8" async defer>
		function Person(name, age){
			this.name = name;
			this.age = age;
		}

		//手动实现new
		function _new(){
			//1.拿到传入的参数中的第一个参数,即构造函数名Func
			var Func = [].shift.call(arguments)
			//2.创建一个空对象obj,并让其继承Func.prototype
			var obj = Object.create(Func.prototype)
			//第二步也可以这样写
			// var obj = {}
			// obj.__proto__ = Func.prototype
			//3.执行构造函数,并将this指向创建的空对象obj
			var ret = Func.apply(obj, arguments)
			//4.如果构造函数返回的值是对象则返回,不是对象则返回创建的对象obj
			return typeof ret === 'object' ? ret : obj
		}

		var p1 = _new(Person, 'bob', 19)
		console.log(p1)
	</script>
</body>
</html>

как понять[].shift.call(arguments) 

Потому что внутренняя реализация shift использует это для представления вызывающего объекта. Затем, когда [].shift.call() передается в объект arguments, точка this исходного метода сдвига изменяется через функцию вызова, чтобы указать на аргументы, и аргументы копируются, а затем возвращается новый массив. На этом цель преобразования массива класса arguments в массив завершена!
На самом деле это можно понимать как разрешение массиву класса вызывать метод массива!

6. Объектно-ориентированный

6.1 Объявление класса и создание экземпляра

Есть два способа объявить класс:

function Animal(name){
	this.name = name;
}

class Animal2 {
  constructor(name){
  	this.name = name;
  }
}


Существует только один способ создать экземпляр класса

var a1 = new Animal('shape');
var a2 = new Animal2('cat');

6.2 Наследование

Наследование может быть реализовано многими способами

6.2.1 Наследование с помощью конструкторов

Сначала посмотрите на код: Parent1 — это родительский класс, а Child1 — подкласс. пройти черезParent1.call(this, name)Изменил этот пункт, чтобы подкласс наследовал свойства родительского класса, то есть у Child1 тоже есть свойство name.

/*
	构造函数实现继承
*/
function Parent1(name){
  this.name = name;
}

function Child1(name, age){
  Parent1.call(this, name)
  this.age = age
}

var c1 = new Child1('bobo', 19)
console.log(c1)


запустите программу и распечатайте результат
image.png

но,Этот метод не может наследовать свойства в цепочке прототипов родительского класса, могут наследоваться только свойства, явно объявленные в родительском классе..
Глядя на код ниже,Parent1.prototype.sayДобавьте метод say к Parent1, чтобы Child1 также мог наследовать?

function Parent1(name){
  this.name = name;
}

Parent1.prototype.say = function(){
  console.log('say hello')
}

function Child1(name, age){
  Parent1.call(this, name)
  this.age = age
}

var p1 = new Parent1('hehe')
var c1 = new Child1('bobo', 19)
console.log(p1)
console.log(c1)


Результат выглядит следующим образом:
В Parent1 есть метод say, но не в Child1, что указывает на то, что он не унаследован.
image.png

6.2.2 Наследование с помощью цепочки прототипов

Принцип реализации состоит в том, чтобы присвоить Child.prototype новому родительскому объекту, т.е.Child2.prototype = new Parent2('bob') 

function Parent2(name){
  this.name = name;
  this.arr = [1,2,3]
}

function Child2(age){
  this.age = age
}

//重点在这句
Child2.prototype = new Parent2('bob')

c2 = new Child2(20)
c3 = new Child2(22)
console.log('c2', c2)
console.log('c3', c3)

Вывод консоли выглядит следующим образом:
image.png

Этот метод также имеет недостатки.Ввиду того, что атрибут arr является массивом, если создаются два объекта экземпляра c2 и c3, поскольку arr этих двух объектов экземпляра указывает на одну и ту же ссылку, изменение значения одного из них также изменит разное.
Давайте посмотрим на следующий эксперимент: значения c2.arr и c3.arr равны [1,2,3], в это время наc2.arr.push(4)Добавьте элемент в c2.arr, и c2.arr станет [1,2,3,4], без проблем. Но посмотрите еще раз на c3.arr, это тоже [1,2,3,4], это проблема, а не то, что мы ожидаем.
image.png

6.2.3 Наследование через композицию

Вышеупомянутые два метода имеют определенные ограничения при использовании по отдельности. Идеально ли сочетать два метода?

/**
 * 组合模式
 */
function Parent3(name){
  this.name = name;
  this.arr = [1,2,3]
}
function Child3(name, age){
  Parent3.call(this, name)
  this.age = age
}
Child3.prototype = new Parent3()

Parent4.prototype.say = function(){
  console.log('say hi')
}

var c4 = new Child3('ciri', 16)
var c5 = new Child3('heha', 32)


Затем проведите эксперимент на консоли.Из результатов мы видим, что подкласс Child3 наследует свойства в цепочке прототипов родительского класса, и один экземпляр изменяет значение arr, не затрагивая другой. Устраните первые два дефекта.
но,При создании экземпляра Child3 конструктор родительского класса Parent3 выполняется дважды, что не является необходимым.
Почему конструктор родительского класса выполняется дважды? так какnew Child3('ciri', 16)Когда в конструкторе подклассаParent3.call(this, name)Конструктор родительского класса выполняется один раз, а затемChild3.prototype = new Parent3()Еще одинnew Parent(), конструктор родительского класса выполняется во второй раз.
Так что его можно еще оптимизировать.

image.png

6.2.4 Комбинированная оптимизация 1

Выше упоминалось, что конструктор родительского класса выполняется дважды, и второй разChild3.prototype = new Parent3(), затем поставьтеnew Parent3()Можно ли его заменить? Да! Согласно знаниям о цепочке прототипов из предыдущей главы, ее можно заменить наChild3.prototype = Parent3.prototype 

//组合方式优化1
function Parent4(name){
  this.name = name;
  this.arr = [1,2,3]
}

function Child4(name, age){
  //重点1
  Parent4.call(this, name)
  this.age = age
}
//重点2
Child4.prototype = Parent4.prototype

Parent4.prototype.say = function(){
  console.log('say hi')
}

var c6 = new Child4('ciri', 16)
var c7 = new Child4('heha', 32)

console.log(c6 instanceof Child4, c6 instanceof Parent4)
console.log(c6.constructor)


Выше приведена комбинированная оптимизация 1, которая решает проблему двойного выполнения конструктора родительского класса.
Идеален ли этот способ? НЕТ!
Посмотрите на последние две напечатанные строки,c6 instanceof Child4 иc6 instanceof Parent4все верно, это нормально.
ноc6.constructorКто это? Обычно это должен быть Child4, но если вы посмотрите на результат печати, то это Parent4.
**
image.png

Почему существует такое явление? Посмотрите еще раз на эту картинку

image.png

Parent4.prototype.constructorНа самом деле он указывает на самого Parent4, потому чтоChild4.prototype = Parent4.prototype, поделитесь объектом-прототипом, поэтомуChild4.prototype.constructorКонечно, это также Parent4.

Затем используйте 6.2.3Child3.prototype = new Parent3()Есть ли у этого метода такая проблема? то же самое, потому чтоChild3Конструктора нет, его конструктор изnew Parent3()Унаследовано, так что это тоже Parent3.

6.2.5 Комбинированная оптимизация 2

Посмотрите прямо на самый совершенный метод записи наследования:

//组合方式优化2
function Parent5(name){
  this.name = name
}
function Child5(name, age){
  Parent5.call(this, name)
  this.age = age
}
Child5.prototype = Object.create(Parent5.prototype)
Child5.prototype.constructor = Child5

var c8 = new Child5()
console.log(c8 instanceof Child5, c8 instanceof Parent5)
console.log(c8.constructor)


Отличие от предыдущего метода заключается в следующем:

Child5.prototype = Object.create(Parent5.prototype)
Child5.prototype.constructor = Child5


**Object.create()** создает новый объект, используя существующий объект для предоставления __proto__ вновь созданного объекта. То есть он возвращает новый объект с указанным объектом-прототипом и свойствами.
Child5.prototype и Parent5.prototype больше не используют одну и ту же ссылку, разделенную новым объектом.
В настоящее время у Child5 нет конструктора, поэтому вам нужно указать его вручную:Child5.prototype.constructor = Child5 
В этот момент родилось идеальное решение для наследования.

Так может быть в 6.2.4Child4.prototype = Parent4.prototypeПишите прямо подChild4.prototype.constructor = Child4Шерстяная ткань? Нет, поскольку они указывают на один и тот же объект, конструктор Child4 изменяется, и конструктор Parent4 также становится Child4.

7. Общение

7.1 Единая политика происхождения и ограничения

Та же политика происхожденияОграничивает взаимодействие документов или сценариев, загруженных из одного источника, с ресурсами из другого источника. Это важный механизм безопасности для изоляции потенциально вредоносных файлов.
Протокол, доменное имя, портПока есть одно различие, это другой источник.

Ограничения из разных источников

  • Cookie, LocalStorage, IndexDB не могут быть получены
  • Не удалось получить DOM.
  • Запросы Ajax не могут быть отправлены (Ajax ограничен использованием одного и того же источника и не может использоваться в разных доменах)

7.2 Как взаимодействуют интерфейс и серверная часть

  • Ajax
  • WebSocket
  • CORS

7.3 Несколько способов междоменной связи

  • JSONP (реализация асинхронной загрузки с использованием тега Script)
  • Хэш (window.location.hash + iframe)
  • postMessage (новое в H5)
  • WebSocket
  • CORS

Справочная статья:сегмент fault.com/ah/119000001…

Восемь, безопасность

Фронтенд-безопасность делится на две категории: CSRF, XSS.
Общие тестовые площадки: основные понятия и аббревиатуры, принципы атаки, меры защиты

8.1 CSRF

CSRF (подделка межсайтовых запросов) Подделка межсайтовых запросов.

принцип атаки

  1. Пользователь C открывает браузер, посещает доверенный веб-сайт A и вводит имя пользователя и пароль, чтобы запросить вход на веб-сайт A;
  2. После проверки информации о пользователе веб-сайт А генерирует информацию о файлах cookie и возвращает ее в браузер.В это время пользователь успешно входит в систему на веб-сайте А, и запрос может быть отправлен на веб-сайт А в обычном режиме;
  3. Прежде чем пользователь покинет веб-сайт А, в том же браузере откройте страницу TAB, чтобы посетить веб-сайт Б;
  4. После того, как веб-сайт B получает запрос пользователя, он возвращает некоторые оскорбительные коды и отправляет запрос на посещение стороннего веб-сайта A;
  5. После получения этих оскорбительных кодов браузер отправляет запрос веб-сайту А по запросу веб-сайта Б, неся информацию о файлах cookie без ведома пользователя. Веб-сайт A не знает, что запрос на самом деле инициирован B, поэтому он будет обрабатывать запрос с полномочиями C в соответствии с информацией из файла cookie пользователя C, что приведет к выполнению вредоносного кода с веб-сайта B.

защитные меры

  1. Проверка токена
  2. Проверка реферера (это легко сделать, но реферер может быть изменен)
  3. Скрыть токен (аналогично проверке токена, сохранить токен в шапке)

8.2 XSS

XSS (межсайтовый скриптинг) атака междоменного скриптинга

принцип атаки

Вставка вредоносного кода скрипта в веб-страницы

защитные меры

  1. HTML: экранируйте эти символы:
&:&amp;
<:&alt;
>:&gt;
':&#x27;
":&quot;
/:&#x2F;
  1. Javascript: экранируйте все символы, кроме буквенно-цифровых, в символы ASCII до 256;
  2. URL-адрес: кодирует ввод пользователя с помощью метода Javascript encodeURIComponent(), который кодирует следующие символы: , , / ? ? : : @ @ & & = = + + $ $ # #

9. Алгоритм

Передняя часть алгоритма не требует слишком многого, рекомендуется сначала просмотреть остальные, а затем просмотреть алгоритм, когда у вас будет энергия.

Сортировать

Существует множество алгоритмов сортировки, и главное — освоить их: быстрая сортировка, сортировка выбором, сортировка по холму и сортировка пузырьком.
срок:

Стабильный: если a изначально находится перед b и a=b, после сортировки a все еще находится перед b; Нестабильный: если a изначально находится перед b и a=b, после сортировки a может появиться после b; Внутренняя сортировка: все операции сортировки выполняются в памяти; Внешняя сортировка: поскольку данные слишком велики, данные помещаются на диск, и сортировка может выполняться только путем передачи данных между диском и памятью; Временная сложность: время, необходимое для выполнения алгоритма. Пространственная сложность: объем памяти, необходимый для запуска программы.

Временная сложность различных алгоритмов:
image.png

Пузырьковая сортировка

Пузырьковая сортировка — это простой алгоритм сортировки. Он неоднократно проходит через последовательность для сортировки, сравнивая два элемента за раз и меняя их местами, если они находятся в неправильном порядке. Работа по посещению последовательности повторяется до тех пор, пока перестановки не понадобятся, то есть последовательность отсортирована. Название этого алгоритма происходит от того факта, что меньшие элементы медленно «вплавляются» в верхнюю часть последовательности путем замены.
временная сложность:

  • Лучший случай: T(n) = O(n)
  • Худший случай: T(n) = O(n^2)
  • Средний случай: T(n) = O(n^2)
//冒泡排序
function bubbleSort(arr){
  if(!arr || arr.length === 0){
    return;
  }
  for(let i=0; i<arr.length; i++){
    for(let j=0; j<i; j++){
      if (arr[i] < arr[j]) {
        //交换两个元素的位置
        [arr[i], arr[j]] = [arr[j], arr[i]]
      }
    }
  }
  return arr;
}

let arr = [2,5,1,8,19,3,32];
console.log('排序前: ', arr)
console.log('冒泡排序后: ', bubbleSort(arr));

//输出
排序前: [2, 5, 1, 8, 19, 3, 32]
冒泡排序后: [1, 2, 3, 5, 8, 19, 32]

сортировка выбором

Сортировка выбором — это простой и интуитивно понятный алгоритм сортировки. Как это работает: сначала найти наименьший (самый большой) элемент в несортированной последовательности, сохранить его в начале отсортированной последовательности, затем продолжить поиск наименьшего (наибольшего) элемента из оставшихся несортированных элементов и поместить его в отсортированную последовательность конец . И так до тех пор, пока все элементы не будут отсортированы.
временная сложность:

  • В лучшем случае: T(n) = O(n^2)
  • Худший случай: T(n) = O(n^2)
  • Средний случай: T(n) = O(n^2)
function selectSort(arr){
  if(!arr || arr.length === 0){
    return arr;
  }
  for(let i=0; i<arr.length; i++){
    let minIndex = i;
    for(let j=i; j<arr.length; j++){
      //找出最小元素的下标
      if(arr[j] < arr[i]){
        minIndex = j;
      }
    }
    //交换两个元素的位置
    [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]
  }
  return arr;
}

стек, очередь, список

Быть совершенным…

рекурсия

Быть совершенным…

Польский и обратный польский

Быть совершенным…

10. Механизм рендеринга

10.1 DOCTYPE и его роль

DTD (определение типа документа, определение типа документа) представляет собой серию грамматических правил, используемых для определения типа документа XML или HTML. Браузеры используют его, чтобы определить тип документа, решить, какой протокол использовать для синтаксического анализа, и переключить режимы браузера.
DOCTYPE используется для объявления типов документов и спецификаций DTD., одно из основных применений — проверка легальности документов. Если код файла недействителен, при его анализе браузером возникнут ошибки.

Примечание: Объявления не чувствительны к регистру.

HTML5

<!DOCTYPE html>

HTML 4.01 Strict

Это DTD содержит все элементы и атрибуты HTML, но не включает презентационные или устаревшие элементы (например, шрифт). Наборы фреймов не допускаются.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

HTML 4.01 Transitional

Это DTD содержит все элементы и атрибуты HTML, включая презентационные или устаревшие элементы (например, шрифт). Наборы фреймов не допускаются.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

HTML 4.01 Frameset

Это DTD такое же, как HTML 4.01 Transitional, но допускает содержимое набора фреймов.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">

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

Эту проблему можно ясно объяснить по этой картинке.
После того, как браузер получает HTML и CSS, он проходитHTML ParserРазобрать HTML вDOM Tree , пройти через CSS ParserРазобрать CSS вStyle Rulesто есть правила CSS, тоDOM Treeи правила CSS объединяются, чтобы сформироватьRender Tree.
Затем выполните компоновку и рисование, и, наконец, Display отобразится на странице.
image.png

10.3 Оплавление

определение

Каждый элемент в структуре DOM имеет свой блок (модель), который требует от браузера расчета в соответствии с различными стилями и размещения элемента там, где он должен появиться в соответствии с результатом расчета.Этот процесс называется перекомпоновкой.

Запустить перекомпоновку

Что вызовет Reflow? (Просто запомните два или три)

  • При добавлении, удалении или изменении узлов DOM это вызовет перекомпоновку или перерисовку.
  • При перемещении позиции DOM или выполнении анимации
  • При изменении стилей CSS
  • Изменение размера окна (нет такой проблемы на мобильном телефоне) или при прокрутке
  • При изменении шрифта по умолчанию на веб-странице

10.4 Перекраска

определение

Когда положение, размер и другие атрибуты различных блоков, такие как цвет, размер шрифта и т. д., определены, браузер рисует эти элементы в соответствии с их соответствующими характеристиками, и появляется содержимое страницы.Этот процесс называется перерисовкой.

Запустить перерисовку

  • изменения модели
  • CSS изменения

Как свести к минимуму перекраску

Например, если вы хотите добавить несколько узлов DOM, добавьте их все сразу, а не по одному.

10.5 отображение: нет и видимость: скрыто

display:none После установки этого свойства элементы под элементом будут скрыты, а занятое пространство исчезнет.
видимость: скрытый После установки элемента, хотя он и невидим, он все равно занимает место в пространстве.

В чем разница между отображением: нет и видимостью: скрыто?

1. Видимость имеет наследование, и его дочерние элементы также будут наследовать это свойство, если установлено visibility:visible, то дочерние элементы будут отображаться.
2.Видимость не влияет на расчет счетчика.Хоть он и скрыт, счетчик продолжает работать.
3. Атрибут видимости поддерживается при переходе CSS3, но отображение не поддерживается, поскольку переход может быть отложен, поэтому использование чистого CSS с видимостью для достижения эффекта отложенного отображения при наведении может улучшить взаимодействие с пользователем.
4. display:none вызовет перекомпоновку (перекомпоновку) и перерисовку, видимость: hidden вызовет перерисовку

11. Механизм работы JS

Освойте следующие моменты:

  • Понимание однопоточной концепции JS
  • Понимание очередей задач
  • Понимание цикла событий
  • Узнайте, какие операторы помещаются в очередь асинхронных задач.
  • Понимать, когда операторы помещаются в очередь асинхронных задач

11.1 Почему JavaScript однопоточный

Главной особенностью языка JavaScript является то, что он является однопоточным, то есть одновременно может выполняться только одно действие. Итак, почему JavaScript не может иметь несколько потоков? Это может повысить эффективность.
Единый поток JavaScript в соответствии с его назначением. В качестве языка сценариев браузера JavaScript в основном используется для взаимодействия с пользователем и управления DOM. Это определяет, что это может быть только один поток, иначе возникнут сложные проблемы с синхронизацией. Например, если предположить, что в JavaScript есть два потока одновременно, один поток добавляет содержимое в узел DOM, а другой поток удаляет этот узел, какой поток должен выбрать браузер?
Таким образом, чтобы избежать сложности, JavaScript с самого начала был однопоточным, что было основной особенностью языка и не изменится в будущем.
Чтобы воспользоваться вычислительной мощностью многоядерных процессоров, HTML5 предлагает стандарт Web Worker, который позволяет сценариям JavaScript создавать несколько потоков, но подпотоки полностью контролируются основным потоком и не должны работать с DOM. Таким образом, этот новый стандарт не меняет однопоточной природы JavaScript.

11.2 Очередь задач

Однопоточный означает, что все задачи должны быть поставлены в очередь, а следующая задача будет выполняться после завершения предыдущей задачи. Если первая задача занимает много времени, вторая задача должна ждать вечно.
Все задачи можно разделить на два типа, один из нихСинхронизировать задачу(синхронно), другойасинхронная задача(асинхронный). Синхронные задачи относятся к задачам, поставленным в очередь для выполнения в основном потоке, и следующая задача может быть выполнена только после выполнения предыдущей задачи; асинхронные задачи относятся к задачам, которые не входят в основной поток, но входят в «очередь задач» ( очередь задач) Задача, только "очередь задач" уведомляет основной поток о том, что асинхронная задача может быть выполнена, задача войдет в основной поток для выполнения.
В частности, рабочий механизм асинхронного выполнения выглядит следующим образом: (То же самое верно и для синхронного выполнения, поскольку его можно рассматривать как асинхронное выполнение без асинхронных задач.)

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。

Пока основной поток пуст, он будет читать «очередь задач», как работает JavaScript. Этот процесс будет повторяться.

11.3 Макрозадачи и микрозадачи

Здесь следует отметить, что new Promise попадет в основной поток для немедленного выполнения, тогда как promise.then является микрозадачей

  • Макро-задача: общий код скрипта, setTimeOut, setInterval
  • Микрозадача (mincro-задача): promise.then, promise.nextTick(узел)

11.4 Цикл событий EventLoop

Основной поток считывает события из «очереди задач», и этот процесс цикличен, поэтому весь механизм работы также называется Event Loop.
image.png

  1. Когда общий скрипт (как первая задача макроса) начнет выполняться, весь код будет разделен на две части: «синхронная задача» и «асинхронная задача»;
  2. Задачи синхронизации будут напрямую поступать в основной поток и выполняться последовательно;
  3. Асинхронные задачи подразделяются на макрозадачи и микрозадачи;
  4. Макро-задача входит в Таблицу событий и регистрирует в ней callback-функцию, при завершении указанного события Таблица событий перемещает функцию в Очередь событий;
  5. Микрозадача также войдет в другую Таблицу Событий и зарегистрирует в ней callback-функцию, после завершения указанного события Таблица Событий переместит эту функцию в Очередь Событий;
  6. Когда задачи в основном потоке выполнены и основной поток пуст, будет проверяться Очередь событий микрозадач, если есть задачи, то будут выполняться все, а если нет, то следующая макро-задача. быть казненным;
  7. Вышеупомянутый процесс будет продолжать повторяться, это цикл событий Event Loop;

11.5 Таймер

В дополнение к размещению событий для асинхронных задач «очередь задач» также может размещать синхронизированные события, которые указывают, через какое время после выполнения определенного кода. Это называется функцией «таймер», которая представляет собой код, который выполняется регулярно.
Функция таймера в основном завершается двумя функциями Setimeate () и Setinterval (). Их внутренние рабочие механизмы точно так же. Разница в том, что код, указанный первым, выполняется один раз, а последнее выполняется несколько раз. Следующее в основном обсуждается SettimeOut ().
SetTimeout() принимает два параметра, первый — функция обратного вызова, второй — количество миллисекунд, которые задерживают выполнение.

console.log(1);
setTimeout(function(){console.log(2);},1000);
console.log(3);

Результатом выполнения приведенного выше кода является 1, 3, 2, потому что setTimeout() задерживает выполнение второй строки до истечения 1000 миллисекунд.
Если второй параметр setTimeout() установлен в 0, это означает, что указанная функция обратного вызова будет выполнена (интервал 0 миллисекунд) сразу после выполнения текущего кода (стек выполнения будет очищен).

setTimeout(function(){console.log(1);}, 0);
console.log(2);

Результат выполнения приведенного выше кода всегда равен 2, 1, потому что только после выполнения второй строки система выполнит callback-функцию в «очереди задач».
Короче говоря, смысл setTimeout(fn,0) состоит в том, чтобы указать, что задача выполняется в самое раннее доступное время простоя основного потока, то есть как можно раньше. Он добавляет событие в конец «очереди задач», поэтому оно не будет выполнено до тех пор, пока не будут обработаны как задача синхронизации, так и существующие события «очереди задач».
Стандарт HTML5 определяет минимальное значение (кратчайший интервал) второго параметра setTimeout(), которое не должно быть меньше4 мс, если оно упадет ниже этого значения, оно автоматически увеличится. До этого старые браузеры устанавливали минимальный интервал в 10 миллисекунд. Кроме того, эти изменения DOM (особенно связанные с повторным рендерингом страницы) обычно выполняются не сразу, аВыполнять каждые 16 мс. В настоящее время эффект от использования requestAnimationFrame() лучше, чем от setTimeout().
Следует отметить, что setTimeout() только вставляет событие в «очередь задач», и основной поток должен дождаться выполнения текущего кода (стека выполнения) перед выполнением указанной им функции обратного вызова. Если текущий код занимает много времени, это может занять много времени, поэтому нет способа гарантировать, что функция обратного вызова будет выполнена во время, указанное setTimeout().

11.6 Что такое асинхронные задачи

  1. setTimeout и setInterval
  2. DOM-события
  3. Promise
  4. сетевой запрос
  5. I/O

11.7 Часто задаваемые вопросы

1) Первый вопрос

Каков результат следующего кода?

console.log(1);
setTimeout(function(){
  console.log(2)
}, 0);
console.log(3)

Ответы: 1, 3, 2
Разобрать:console.log()это задача синхронизации,setTimeoutявляется асинхронной задачей. Асинхронные задачи будут ждать завершения синхронных задач перед выполнением. Несмотря на то что setTimeoutУстановленная задержка равна 0, но браузер устанавливает минимальную задержку в 4 мс, поэтомуconsole.log(2)помещается в очередь задач через 4 мс. Когда задача синхронизации выполняется, то есть после печати 1 и 3, основной поток извлекает задачу из очереди задач и печатает 2.

2) Вопрос 2

Что выводит следующий код

console.log('A')
while(true){}
console.log('B')

Ответ: А
Анализ: код выполняется сверху вниз, сначала печатается A, а затем цикл while, поскольку условие всегда истинно, он войдет в бесконечный цикл. Пока не будет выполняться, пока не будет выполнена третья строка.

Также есть вариация на эту тему:

console.log('A');
setTimeout(function(){
  console.log('B')
}, 0);
while(1){}

Опять же, будет выведено только A. Поскольку асинхронная задача должна дождаться выполнения синхронной задачи перед выполнением, а входит в бесконечный цикл, поэтому B не будет напечатано.

3) Третий вопрос

Следующий код выводит результат

for(var i=0; i<4; i++){
  setTimeout(function(){
    console.log(i)
  }, 0)
}

Результат: 4 из 4.
Анализ: этот вопрос в основном исследует время, когда асинхронные задачи помещаются в очередь задач. при выполнении кsetTimeoutТо есть при использовании таймера асинхронная задача не сразу будет поставлена ​​в очередь задач, а будет поставлена ​​по истечении времени. Затем, после выполнения задач синхронизации в стеке выполнения, задачи последовательно удаляются из очереди задач для выполнения.
Цикл for является синхронной задачей, и цикл будет выполнен первым.В это время значение i равно 4. Через 4 мсconsole.log(i)ставятся в очередь задач по очереди.При этом, если в стеке выполнения нет задачи синхронизации, задачи вынимаются из очереди задач по очереди, то есть печатается 4 4s.

Итак, как я могу напечатать 0, 1, 2, 3, как ожидалось? Есть три метода:

//方法1:把 var 换成 let
for(let i=0; i<4; i++){
  setTimeout(function(){
    console.log(i)
  }, 0)
}

//方法2:使用立即执行函数
for(let i=0; i<4; i++){
  (function(i){
    setTimeout(function(){
      console.log(i)
    }, 0)
  })(i)
}

//方法3:加闭包
for(let i=0; i<4; i++){
  var a = function(){
    var j = i;
    setTimeout(function(){
      console.log(j)
    }, 0)
  }
  a();
}

4) Вопрос 4

setTimeout(function(){
    console.log(1)
});
new Promise(function(resolve){
    console.log(2);
    for(var i = 0; i < 10000; i++){
        i == 9999 && resolve();
    }
}).then(function(){
    console.log(3)
});
console.log(4);
执行结果:
// 2, 4, 3, 1

анализировать:
1.setTimeout является асинхронным, и это макрофункция, которая помещается в очередь макрофункций;
2. Новый Promise — это синхронная задача, которая выполняется напрямую, выводит 2 и выполняет цикл for;
3. Promise.then — микрозадача, которая ставится в очередь микрозадач;
4.console.log(4) задача синхронизации, выполнить напрямую, вывести 4;
5. В это время, когда выполняется задача основного потока, проверьте наличие обещания. Затем в очереди микрозадач выполните микрозадачу и напечатайте 3;
6. После выполнения микрозадачи первый цикл завершается, взять первую макрозадачу из очереди макрозадач на выполнение в основной поток и вывести 1;
7. Результаты: 2, 4, 3, 1

5) Вопрос 5

console.log(1);

setTimeout(function() {
  console.log(2);
}, 0);

Promise.resolve().then(function() {
  console.log(3);
}).then(function() {
  console.log('4.我是新增的微任务');
});

console.log(5);

执行结果:
// 1,5,3,4.我是新增的微任务,2

анализировать:
1.console.log(1) — это задача синхронизации, выполнить ее напрямую, вывести 1;
2.setTimeout является асинхронным, и это макрофункция, которая помещается в очередь макрофункций;
3. Promise.resolve().then — микрозадача, которая ставится в очередь микрозадач;
4. console.log(5) — это задача синхронизации, запустите ее напрямую и напечатайте 5;
5. В это время, когда выполняется задача основного потока, проверьте наличие Promise.resolve(). Затем в очереди микрозадач выполните микрозадачу и напечатайте 3;
6. В это время обнаруживается, что вторая задача .then относится к микрозадаче, она добавляется в очередь микрозадач, выполняется и печатается 4. Я новая микрозадача;
7. Здесь подчеркивается, что во время выполнения микрозадач, если будет обнаружена новая микрозадача, новая микрозадача будет добавлена ​​в очередь, после последовательного выполнения очереди микрозадач будет выполнен следующий цикл;
8. После выполнения микрозадачи первый цикл завершается, вынести первую макрозадачу setTimeout в очередь макрозадач в основной поток на выполнение и вывести 2;
9. Результаты: 1, 5, 3, 4. Я недавно добавленная микрозадача, 2

6) Вопрос 6

function add(x, y) {
  console.log(1)
  setTimeout(function() { // timer1
    console.log(2)
  }, 1000)
}
add();

setTimeout(function() { // timer2
  console.log(3)
})

new Promise(function(resolve) {
  console.log(4)
  setTimeout(function() { // timer3
    console.log(5)
  }, 100)
  for(var i = 0; i < 100; i++) {
    i == 99 && resolve()
  }
}).then(function() {
  setTimeout(function() { // timer4
    console.log(6) 
  }, 0)
  console.log(7)
})

console.log(8)

执行结果
//1,4,8,7,3,6,5,2

анализировать:
1.add() — синхронная задача, выполняется напрямую, выводит 1;
2. setTimeout в add() — это асинхронная задача и макрофункция, которая записывается как timer1 и помещается в очередь макрофункций;
3. setTimeout ниже add() — это асинхронная задача и макрофункция, которая записывается как timer2 и помещается в очередь макрофункций;
4. new Promise — это синхронная задача, выполняемая напрямую, выводим 4;
5. setTimeout в Promise — это асинхронная задача и макрофункция, которая записывается как timer3 и помещается в очередь макрофункций;
6. Цикл for в Promise синхронизирует задачи и выполняет код;
7. Promise.then — микрозадача, поставьте ее в очередь микрозадач;
8. console.log(8) — это задача синхронизации, запустите ее напрямую, выведите 8;
9. В это время, когда задача основного потока выполняется, проверьте очередь микрозадач, там есть Promise. Затем выполните микрозадачу и обнаружите, что setTimeout — это асинхронная задача и макрофункция, запишите ее как timer4 и поместите его в очередь макрофункций;
10. console.log(7) в очереди микрозадач является синхронной задачей, выполните ее напрямую и выведите 7;
11. После выполнения микрозадачи первый цикл завершается;
12. Проверьте таблицу событий задачи макроса, которая содержит таймер 1, таймер 2, таймер 3, таймер 4, четыре задачи макроса таймера в соответствии со временем задержки таймера, чтобы получить порядок, который может быть выполнен, а именно очередь событий: таймер 2, таймер 4, таймер 3, таймер 1. , убрать очередь в первый timer2;
13. Выньте timer2 для выполнения, console.log(3) для синхронизации задачи, выполните ее напрямую и напечатайте 3;
14. Нет микрозадачи, заканчивается второй Event Loop;
15. Выньте timer4 для выполнения, console.log(6) для синхронизации задачи, выполните ее напрямую и напечатайте 6;
16. Нет микрозадачи, заканчивается третий Event Loop;
17. Выньте timer3 для выполнения, console.log(5) для синхронизации задачи, выполните ее напрямую и напечатайте 5;
18. Нет микрозадачи, заканчивается четвертый цикл событий;
19. Выньте timer1 для выполнения, console.log(2) для синхронизации задачи, выполните ее напрямую и напечатайте 2;
20. Нет ни микрозадач, ни макрозадач, и пятый цикл событий заканчивается;
21. Результаты: 1, 4, 8, 7, 3, 6, 5, 2

7) Вопрос 7

setTimeout(function() { // timer1
  console.log(1);
  setTimeout(function() {  // timer3
    console.log(2);
  })
}, 0);
setTimeout(function() {  // timer2
  console.log(3);
}, 0);

执行结果
//1,3,2

анализировать:
1. Первый setTimeout — это асинхронная задача и макрофункция, записанная как timer1 и помещенная в очередь макрофункций;
2. Третий setTimeout — это асинхронная задача и макрофункция, которая записывается как timer2 и помещается в очередь макрофункций;
3. Нет микрозадачи, заканчивается первый Event Loop;
4. Извлеките timer1, задачу синхронизации console.log(1), запустите ее напрямую и напечатайте 1;
5. setTimeout в timer1 — это асинхронная задача и макрофункция, которая записывается как timer3 и помещается в очередь макрофункций;
6. Нет микрозадачи, заканчивается второй Event Loop;
7. Извлеките timer2, задачу синхронизации console.log(3), выполните ее напрямую и напечатайте 3;
8. Нет микрозадачи, заканчивается третий Event Loop;
9. Выньте timer3, задачу синхронизации console.log(2), запустите ее напрямую и напечатайте 2;
10. Нет ни микрозадач, ни макрозадач, и четвертый цикл событий заканчивается;
11. Результаты: 1, 3, 2

12. Производительность страницы

Интервью надо тестировать, эти пять лучше всего запомнить. Асинхронная загрузка и кеширование браузера расширяют вопрос, а остальные три просто нужно сказать.

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

  1. Слияние сжатия ресурсов для уменьшения HTTP-запросов
  2. Асинхронная загрузка неосновного кода (способ асинхронной загрузки, отличие асинхронной загрузки)
  3. Использовать кеш браузера (классификация кеша, принцип кеширования)
  4. Используйте CDN
  5. Предварительно разрешенный DNS
//强制打开 <a> 标签的 dns 解析
<meta http-equiv="x-dns-prefetch-controller" content="on">
//DNS预解析
<link rel="dns-prefetch" href="//host_name_to_prefetch.com">

12.1 Асинхронная загрузка

Как загрузить асинхронно

  1. Динамическая загрузка скрипта
  2. defer
  3. async

Разница между асинхронной загрузкой

  1. defer выполняется после разбора HTML, если их несколько, они выполняются в порядке загрузки.deferсценарий будет вDOMContentLoadedиloadВыполняется перед событием.
  2. Async выполняется сразу после загрузки скрипта, если их несколько, то порядок выполнения не имеет ничего общего с порядком загрузки.asyncБудет вloadвыполняется до события, но не гарантируется работа сDOMContentLoadedпорядок исполнения.


Следующие два рисунка иллюстрируют это более наглядно.deferиasyncреализация иDOMContentLoaded,loadСобытие отношения:

image.png

image.png

12.2 Кэш браузера

Классификация стратегий кэширования:

  • Сильный кеш
  • Согласовать кеш

Стратегии кэширования реализуются путем установки заголовков HTTP.
Каждый раз, когда браузер инициирует запрос, он сначала ищет результат запроса и идентификатор кеша в кеше браузера.
Каждый раз, когда браузер получает возвращенный результат запроса, он сохраняет результат и идентификатор кеша в кеше браузера.

12.2.1 Сильный кеш

Сильный кеш: запрос на сервер не отправляется, а ресурсы считываются непосредственно из кеша. из кеша памяти. Надежного кэширования можно добиться, установив два HTTP-заголовка: Expires и Cache-Control.

1. Expires

Время истечения срока действия кэша используется для указания времени истечения срока действия ресурса, что является конкретным моментом времени на стороне сервера.. То есть Expires=max-age + время запроса, которое нужно использовать вместе с Last-modified. Expires — это поле заголовка ответного сообщения веб-сервера, которое сообщает браузеру, что браузер может напрямую извлекать данные из кеша браузера до истечения срока действия без повторного запроса.
Expires — это продукт HTTP/1 и ограничен местным временем. Если местное время изменено, это может привести к аннулированию кеша..Expires: Wed, 22 Oct 2018 08:41:00 GMTУказывает, что ресурс истекает после ср., 22 октября 2018 года 08:41:00 GMT, нужно запросить еще раз.

2. Cache-Control

В HTTP/1.1 Cache-Control является наиболее важным правилом, в основном используемым для управления кэшированием веб-страниц. например, когдаCache-Control:max-age=300, это означает, что ресурс будет загружен снова в течение 5 минут после правильного времени возврата запроса (браузер также зафиксирует это), и сильный кеш будет сбит.
Cache-Control может быть установлен в заголовках запроса или ответа и может быть объединен с различными директивами:
image.png

3. Сравнение Expires и Cache-Control

На самом деле между ними нет большой разницы, разница в том, что Expires является продуктом http1.0, а Cache-Control — продуктом http1.1.Если оба существуют одновременно, Cache-Control имеет более высокий приоритет, чем Expires.; В некоторых средах, не поддерживающих HTTP1.1, вступает в действие Expires. Так что Expires на самом деле устаревший продукт, и его существование на данном этапе — это просто способ написания совместимости.
Сильный кеш определяет, основан ли кеш на том, превышает ли он определенное время или определенный период времени, и не заботится о том, был ли обновлен файл на стороне сервера, что может привести к тому, что загруженный файл не будет самым последним содержимым на на стороне сервера, так откуда мы знаем содержимое на стороне сервера? Произошло ли обновление? На этом этапе нам нужно использовать согласованную стратегию кэширования.

12.2.2 Кэш согласования

Согласование кеша — это процесс, в котором браузер инициирует запрос к серверу с идентификатором кеша после принудительного отказа кеша, и сервер решает, использовать ли кеш на основе идентификатора кеша. Есть два основных случая:

  • Кэш согласования вступает в силу, возвращает 304 и не изменен
  • Согласовать аннулирование кеша, вернуть 200 и запросить результат

Согласованное кэширование может быть достигнуто путем установки двух HTTP-заголовков: Last-Modified и ETag.

1. Last-Modified и If-Modified-Since

Когда браузер обращается к ресурсу в первый раз, когда сервер возвращает ресурс, он добавляет заголовок Last-Modified в заголовок ответа, значением является время последней модификации ресурса на сервере, и браузер кэширует файл. и заголовок после его получения;

Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT

В следующий раз, когда браузер запрашивает этот ресурс, он обнаруживает наличие заголовка Last-Modified, поэтому добавляет заголовок If-Modified-Since, а значением является значение Last-Modified; сервер снова получает этот запрос ресурса. , согласно If- Значение в Modified-Since сравнивается со временем последней модификации ресурса на сервере.Если изменений нет, возвращаем 304 и пустое тело ответа и читаем его прямо из кеша.Если время If-Modified-Since меньше времени последней модификации ресурса на сервере Время модификации, что указывает на то, что файл был обновлен, поэтому верните новый файл ресурсов и 200.
Но у Last-Modified есть некоторые недостатки:

  • Если файл кеша открыт локально, даже если файл не изменен, это все равно приведет к изменению Last-Modified, и сервер не сможет обратиться к кешу и отправить тот же ресурс.
  • Поскольку Last-Modified может быть подсчитан только в секундах, если файл изменяется в незаметное время, сервер будет думать, что ресурс все еще используется, и не будет возвращать правильный ресурс.

Поскольку вопрос о том, недостаточно ли кэша, определяется на основе времени модификации файла, можно ли определить стратегию кэширования непосредственно на основе того, было ли изменено содержимое файла? Так в HTTP/1.1 пришлиETagиIf-None-Match

2. ETag и If-None-Match

Etag – это уникальный идентификатор (генерируемый сервером) текущего файла ресурсов, который возвращается, когда сервер отвечает на запрос. Пока ресурс изменяется, Etag будет создаваться повторно.. В следующий раз, когда браузер загрузит ресурс и отправит запрос на сервер, он поместит значение Etag, возвращенное в прошлый раз, в If-None-Match в заголовке запроса.Серверу нужно только сравнить отправленное If-None-Match. клиентом со своим собственным сервером.Если ETag ресурса непротиворечив, можно судить о том, был ли ресурс изменен по отношению к клиенту. Если сервер обнаружит, что ETag не совпадает, он напрямую отправит новый ресурс (включая новый ETag) клиенту в виде обычного возвращаемого пакета GET 200; если ETag непротиворечив, он напрямую вернет 304 на уведомить клиента напрямую. Просто используйте локальный кеш.

3. Сравнение между ними:
  • Во-первых, Etag лучше, чем Last-Modified, с точки зрения точности.

Единицей времени Last-Modified являются секунды.Если файл изменяется несколько раз в течение 1 секунды, то их Last-Modified на самом деле не отражает модификацию, но Etag будет меняться каждый раз, чтобы обеспечить точность; если это балансировка нагрузки Последнее изменение, созданное каждым сервером, также может быть несовместимым.

  • Во-вторых, по производительности Etag уступает Last-Modified, ведь Last-Modified нужно только записывать время, а Etag нужен сервер для вычисления хеш-значения по алгоритму.
  • В-третьих, с точки зрения приоритета проверка сервера отдает приоритет Etag.

12.2.3 Механизм кэширования

Обязательное кэширование имеет приоритет над согласованным кэшированием. Если обязательное кэширование (Expires и Cache-Control) действует, кеш используется напрямую. Если оно не действует, выполняется согласованное кэширование (Last-Modified / If-Modified-Since и Etag /If-None-Match) согласованный кеш определяется сервером, следует ли использовать кеш. Если согласованный кеш недействителен, то кеш, представляющий запрос, недействителен, вернуть 200, вернуть ресурс и идентификатор кеша, а затем сохраните его в кеше браузера; если он действителен, верните 304 и продолжайте использовать кеш.

12.2.4 Разница между сильным кешем и кешем согласования

Разницу между сильным кешем и согласованным кешем можно представить в следующей таблице:

тип кэша Получить форму ресурса код состояния отправить запрос на сервер
Сильный кеш получить из кеша 200 (из кеша) Нет, получить напрямую из кеша
Согласовать кеш получить из кеша 304 (не изменено) Да, сообщить серверу, доступен ли кеш


Влияние поведения пользователя на кеширование

Действие пользователя Expires/Cache-Control Last-Modied/Etag
Введите в адресной строке эффективный эффективный
переход по ссылке на страницу эффективный эффективный
новое окно эффективный эффективный
вперед и назад эффективный эффективный
F5 обновить недействителен эффективный
Ctrl+F5 Принудительно обновить недействителен недействителен

12.2.5 Сравнение кэша памяти и дискового кэша

В консоли Network в браузере chrome полоса размера обычно имеет три состояния
1.from memory cache
2.from disk cache
3. Размер самого ресурса (например: 1.5k)

Три отличия:

  • from memory cache: Буквальное значение из памяти, но это также буквальное значение.Этот ресурс берется напрямую из памяти, и сервер не запрашивается.Как правило, ресурс уже загружен и закэширован в памяти.Когда страница закрыта, ресурс будет освобожден памятью, и кеш памяти не появится, когда та же страница снова откроется.
  • from disk cache: Аналогично предыдущему, этот ресурс берется с диска, и ресурс был загружен в определенное время до этого, сервер не будет запрашиваться, но этот ресурс не будет освобожден при закрытии страницы, потому что есть жесткий диск Среди них, в следующий раз, когда вы его откроете, он все равно будет из кеша диска
  • Размер самого ресурса: При статусе http 200 ресурс фактически получен из браузера. При статусе http 304 число представляет собой размер сообщения связи с сервером, а не размер самого ресурса. Ресурс получается локально .
государство тип инструкция
200 form memory cache Не запрашивать сетевые ресурсы, ресурсы находятся в памяти, а общие скрипты, шрифты и картинки будут храниться в памяти.
200 form disk ceche Не запрашивает сетевые ресурсы, на диске вообще не скрипты будут в памяти, типа css и тд.
200 Значение размера ресурса Значение размера ресурса Загрузите последний ресурс с сервера.
304 Размер пакета Сервер запросов обнаруживает, что ресурс не был обновлен, и использует локальный ресурс, то есть обращается к кэшу согласования.

Тринадцать, мониторинг ошибок

13.1 Неправильная классификация внешнего интерфейса

Ошибки внешнего интерфейса делятся на две большие категории:

  • Немедленная ошибка запуска (ошибка кода)
  • ошибка загрузки ресурса

13.2 Неправильный способ ловли

Как ловить ошибки на лету

  • try...catch
  • window.onerror

Обнаружение ошибки загрузки ресурса:

  • object.onerror
  • performance.getEntries()
  • Захват событий ошибки

window.onerror может обнаруживать только немедленные ошибки времени выполнения, а не ошибки загрузки ресурсов, потому что ошибки загрузки ресурсов не всплывают.
Ошибки загрузки ресурсов можно получить перехватом Error, демонстрация кода:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>错误监控</title>
	<link rel="stylesheet" href="">
	<script type="text/javascript">
		window.addEventListener("error", function(e){
			console.log('捕获了错误:', e)
		}, true)
	</script>
</head>
<body>
	<script src="//baidu.con/test.js" charset="utf-8"></script>
</body>
</html>

#### Можно ли отловить междоменные ошибки выполнения js? Что такое сообщение об ошибке и как с этим бороться Можно поймать, ошибка следующая:
![image.png](https://cdn.nlark.com/yuque/0/2020/png/252511/1581861516950-8588fc6a-1f3d-46a2-a361-034e1063baa0.png#align=left&display=inline&height=143&margin=%5Bobject%20Object%5D&name=image.png&originHeight=286&originWidth=767&size=111174&status=done&style=none&width=383.5)

Как с этим бороться?
  1. Добавьте атрибут crossorigin в тег скрипта (это делает клиент)
  2. Установить заголовок ответа js-ресурса Access-Control-Allow-Origin:* (на стороне сервера)

### 13.3 Обоснование сообщения об ошибках
  1. Отчет с использованием связи Ajax (в основном бесполезен)
  2. Используйте объект изображения для отчета (в основном используйте этот способ)
<script type="text/javascript">
  (new Image()).src = 'http://www.baidu.com/test?t=hahha';
</script>

Четырнадцать, это, звони, применяй, связывай

14.1 Что общего у call и apply

  • Оба могут изменить контекст, в котором выполняется функция, и передать метод одного объекта другому объекту для выполнения, и он выполняется немедленно.
  • Объект, для которого вызываются call и apply, должен быть функцией.

14.2 Разница между вызовом и применением

Разница в основном отражается в параметрах.

Как написать звонок:

Function.call(obj,[param1[,param2[,…[,paramN]]]])
  • Объект для вызова call должен быть функцией.
  • Первым параметром вызова является объект. Вызывающий функцию укажет на этот объект. Если не передано, по умолчанию используется окно глобального объекта.
  • Начиная со второго параметра, он может принимать любое количество параметров. Каждый параметр сопоставляется с параметром функции в соответствующей позиции. Но если все параметры передаются в виде массива, они будут сопоставлены с первым параметром, соответствующим функции в целом, и тогда параметры будут пустыми.
function func (a,b,c) {}
func.call(obj, 1,2,3)
// func 接收到的参数实际上是 1,2,3
func.call(obj, [1,2,3])
// func 接收到的参数实际上是 [1,2,3],undefined,undefined

Как написать заявку

Function.apply(obj[,argArray])
  • Его вызывающей стороной должна быть функция Function, и она принимает только два параметра.Правила для первого параметра такие же, как и для вызова.
  • Второй параметр, который должен быть массивом или подобным массиву, будет преобразован в массивы, подобные массиву, переданы в функцию и сопоставлены с соответствующими параметрами функции. Это также важное различие между вызовом и применением.
func.apply(obj, [1,2,3])
// func 接收到的参数实际上是 1,2,3
func.apply(obj, {
    0: 1,
    1: 2,
    2: 3,
    length: 3
})
// func 接收到的参数实际上是 1,2,3

14.3 Цель вызова и подачи заявки

Некоторые сценарии использования вызова и применения перечислены ниже. Отказ от ответственности: в примере нет сцены, где нужно использовать call или apply, это просто личная привычка.

сценарии использования звонков

1. Наследование объектов. Например, следующий пример:

function superClass () {
    this.a = 1;
    this.print = function () {
        console.log(this.a);
    }
}
function subClass () {
    superClass.call(this);
    this.print();
}
subClass();
// 1

Подкласс наследует метод печати и переменную суперкласса через метод вызова. Кроме того, подкласс также может расширять свои собственные методы.
2. Метод заимствования. Помните массив классов только что? Если он хочет использовать методы в цепочке прототипов Array, он может сделать это:

let domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));

Таким образом, domNodes могут применять все методы в Array.

Несколько замечательных применений apply

1. Мат.макс.. Используйте его, чтобы получить самый большой элемент в массиве.

let max = Math.max.apply(null, array);

Точно так же, чтобы получить наименьший элемент в массиве, вы можете сделать это:

let min = Math.min.apply(null, array);

2. Реализовать комбинацию двух массивов. До оператора распространения ES6 мы могли сделать это с помощью Array.prototype.push.

let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
Array.prototype.push.apply(arr1, arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]

14.4 Использование привязки

Наконец, давайте поговорим о привязке. Объяснение MDN: метод bind() создает новую функцию, которая при вызове устанавливает ключевое слово this в предоставленное значение. И когда вызывается новая функция, данный список параметров используется как несколько первых элементов последовательности параметров исходной функции.
Его синтаксис следующий:

Function.bind(thisArg[, arg1[, arg2[, ...]]])

Метод bind похож на apply и call в том смысле, что он также может изменять указатель this в теле функции. разница в том,Возвращаемое значение метода привязки — это функция, и ее необходимо вызвать позже для выполнения.. С другой стороны, apply и call вызываются немедленно.
Рассмотрим следующий пример:

function add (a, b) {
    return a + b;
}
function sub (a, b) {
    return a - b;
}
add.bind(sub, 5, 3); // 这时,并不会返回 8
add.bind(sub, 5, 3)(); // 调用后,返回 8

Если первый параметр bind имеет значение null или не определен, это относится к окну глобального объекта.

Суммировать

Основная функция вызова и применения — изменить контекст выполнения объекта и немедленно его выполнить. Они немного по другому пишутся по параметрам.
Bind также может изменить контекст выполнения объекта.В отличие от call и apply, возвращаемое значение представляет собой функцию, которую необходимо вызвать позже для выполнения.

15. Дроссельная защита от сотрясений

Anti-shake: после срабатывания высокочастотного функционального события функция может быть выполнена только один раз в течение n секунд.Если событие сработает снова в течение n секунд, время будет пересчитано.
Регулирование: так называемое регулирование означает, что событие запускается непрерывно, но функция выполняется только один раз в n секунд. Дросселирование снижает частоту выполнения функции

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>防抖节流2</title>
	<link rel="stylesheet" href="">
</head>
<body>
	<script type="text/javascript">
		//防抖
		function debounce(func, wait){
			let timeout;
			return function(){
				if(timeout){
					clearTimeout(timeout)
				}
				timeout = setTimeout(() => {
					func.apply(this, arguments)
				}, wait)
			}
		}

		//节流
		function throttle(func, wait){
			let timeout;
			return function(){
				if(!timeout){
					timeout = setTimeout(() => {
						timeout = null;
						func.apply(this, arguments)
					}, wait)
				}
			}
		}

		function say(){
			console.log('hi haha')
		}

		// document.onmousemove = debounce(say, 1000)
		document.onmousemove = throttle(say, 1000)
	</script>
</body>
</html>

Наконец, я желаю вам всем гладкого интервью и мягкого предложения~
Большие ребята также могут добавить wx для обмена советами:solocoder, проверить ввод сообщения前端 или面试, потяните переднюю коммуникационную группу, чтобы грести вместе...



Справочная статья:
Подробное объяснение механизма работы js (Event Loop)
woo woo Краткое описание.com/afraid/oh 06 oh 86EF2…

Глубокое понимание механизма кэширования браузера
Краткое описание.com/afraid/54 Цао Цао 04190…

В «Галантерее» подробно рассказывается о различии и использовании терминов «вызвать, применить и связать».
сегмент fault.com/ah/119000001…