введение
Большое спасибо за все проблемы, которые вы указали в комментариях. Из-за большого количества изменений в прошлом году он был отложен, а проблемы и предложения, на которые указали большие ребята, были исправлены. Пожалуйста, будьте уверены, чтобы поесть! Спасибо~🥳
В настоящее время, столкнувшись с самой серьезной интернет-зимой за последние годы, чаще всего звучит фраза: встречайтесь в реках и озерах~🤣. Сокращения ЧК и увольнения бесконечны, и все в панике. Но блоггеры всегда считают, что,Холодной зимой таланты еще дороже. Пока есть отличная работа и оборудование, при встречном ветре также может быть волна урожая и возвращения.
Несколько лет назад блогер тоже пережил много боев и, наконец, получил предложения от многих крупных производителей. В процессе затворничества и самосовершенствования я составил для себя набор читов с интервью для многократного изучения, а позже раздал их нескольким нуждающимся братьям. Поэтому я решил потратить немного энергии на его организацию, чтобы каждый мог учиться более систематически и быстро совершенствоваться.
Навыки на собеседовании есть, но это точно не подлог и жульничество.После короткого промежутка времени можно отступить на практику, выйти на уборку, шагнуть на большой завод и удвоить зарплату.Разве это не круто ? 🤓
Средняя часть была недавно выпущена, быстро введите
Блог Xiaocaiji выпрашивает лайки 🙂blog
Принципы выращивания
Наверное, всем очень надоели письменные тесты и очки знаний. Потому что на самом деле в реальном бою упор делается на эффективность развития, и редко кто намеренно записывает какие-то детали и копает глубокие знания.В голове какие-то разрозненные точки знаний, которые нельзя системно связать в сеть, и были в знакомой ситуации.состоянии. Я не знаю, сколько людей похожи на блоггеров.Пока что каждый раз, когда я пишу, чтобы перестать пузыриться, мне нужно гуглить, как это пишется. 🤪.
В таком состоянии точно невозможно пересечь поле боя интервью. По сути, собеседование похоже на экзамен: если подумать о том, что вы делали перед вступительными экзаменами в колледж, то это не более чемпониматьа такжесистемная ассоциативная память. В этой читбуке много пунктов знаний, потратив некоторое время на то, чтобы понять и запомнить их один за другим, вы, естественно, поймете и будете бесстрашны.
Поскольку эту книгу-шпаргалку легко запомнить, она может быстро перейти в состояние сдачи теста, что похоже на повторение плана знаний. Точки знаний будут пытаться упростить и уточнить контекст знаний, не будут вдаваться в подробности и охватывать все. Детская обувь, которые заинтересованы или у которых есть вопросы, могут найти информацию о соответствующих точках знаний в Google. 😋
CSS
1. Блочная модель
Когда страница визуализируется, элемент dom принимаетмакет макета. доступныйbox-sizingСделайте настройки. По рассчитанной ширине и высоте площади можно разделить на:
-
content-box(Стандартная блочная модель W3C) -
border-box(коробочная модель IE) -
padding-box(FireFox используется для поддержки) -
margin-box(не реализовано браузерами)
Советы: Теоретически существует 4 вышеперечисленных вида ящиков, но сейчас они поддерживаются только в спецификациях w3c и mdn.
content-boxа такжеborder-box;
2. BFC
контекст форматирования на уровне блока, представляет собой независимую область рендеринга, которая изолирует элементы внутри BFC от внешних элементов, так что расположение внутренних и внешних элементов не влияет друг на друга.
Макет под IE, который может запускаться зумом:1
-
Условия срабатывания:
- корневой элемент
position: absolute/fixeddisplay: inline-block / table-
floatэлемент -
ovevflow!==visible
-
правило:
- Два соседних ящика, принадлежащие одному и тому же BFC, расположены вертикально.
- Поля двух соседних блоков, принадлежащих одному и тому же BFC, будут перекрываться.
- Левая сторона поля поля дочернего элемента в BFC касается левой стороны поля границы содержащего блока (BFC) (за исключением абсолютного дочернего элемента).
- Область BFC не пересекается с областью элемента float.
- При расчете высоты БФК в расчете также участвуют плавающие дочерние элементы
- Текстовый слой не будет закрыт плавающим слоем, обтекающим
-
заявление:
- Не допустить
marginперекрытие - Может содержать плавающие элементы - четкий внутренний плавающий (принцип очистки плавающего - два
divрасположены в одном районе BFC) - Адаптивный двухколоночный макет
- Может предотвратить закрытие элементов плавающими элементами
- Не допустить
3. Каскадный контекст
Элемент перемещается на специальный слой в трехмерном пространстве.(ось Z)На один уровень выше обычных элементов.
-
Условия срабатывания
- контекст корневого стека (
html) position- css3 свойства
flextransformopacityfilterwill-change-webkit-overflow-scrolling
- контекст корневого стека (
-
Уровень наложения: порядок контекстов наложения по оси Z.
- Каскадные уровни имеют смысл только в одном контексте стека.
-
z-indexнаивысший приоритет
4. Макет по центру
-
Центрировано по горизонтали
- Встроенные элементы:
text-align: center - Элементы уровня блока:
margin: 0 auto absolute + transformflex + justify-content: center
- Встроенные элементы:
-
Центрировать по вертикали
line-height: heightabsolute + transformflex + align-items: centertable
-
Центрируется по горизонтали и вертикали
absolute + transformflex + justify-content + align-items
5. Приоритет селектора
-
!important> Встроенные стили >#id>.class>tag> * > Наследовать > По умолчанию - Селекторсправа налевоРазобрать
6. Удалите плавающий эффект, чтобы предотвратить падение высоты родителя.
- Очистить поплавок, добавив хвостовой элемент
:after / <br> : clear: both
- Создать родительский BFC
- высота родительского набора
7. Разница между ссылкой и @import
-
linkЕсть много функций, вы можете определить RSS, определить Rel и другие функции, и@importМожет использоваться только для загрузки css - при разборе на
link, страница будет синхронно загружать указанный css, и@importСсылочный css не будет загружен до тех пор, пока страница не будет загружена -
@importТребуется IE5+ для использования -
linkЕго можно импортировать динамически с помощью js,@importнет
8. Препроцессор CSS (Sass/Less/Postcss)
Принцип препроцессора CSS заключается в том, чтобы передать CSS-подобный язык черезКомпиляция веб-пакетаПреобразован в настоящий CSS, который читается браузером. Поверх этого уровня компиляции CSS можно наделить все более и более мощными функциями.
- вложенный
- Переменная
- оператор цикла
- Условные операторы
- автоматический префикс
- преобразование единиц измерения
- повторное использование примеси
В интервью мы не будем акцентировать внимание на этом моменте, в общем, вы можете поделиться своим опытом в реальном проекте~
9. CSS-анимация
-
transition: анимация перехода-
transition-property: Атрибуты -
transition-duration: интервал -
transition-timing-function: изгиб -
transition-delay: Задерживать - Общие крючки:
transitionend
-
-
animation / keyframes-
animation-name: имя анимации, соответствующее@keyframes -
animation-duration: интервал -
animation-timing-function: изгиб -
animation-delay: Задерживать -
animation-iteration-count: раз-
infinite: циклическая анимация
-
-
animation-direction: направление-
alternate: Воспроизведение в обратном порядке
-
-
animation-fill-mode: неподвижный режим-
forwards: при остановке сохранить последний кадр -
backwards: При остановке вернуться к первому кадру -
both: Использовать одновременноforwards / backwards
-
- Общие крючки:
animationend
-
-
Свойства анимации: попробуйте использовать свойства анимации для анимации, которые могут иметь лучшую производительность.
translatescalerotateskewopacitycolor
Опыт
Обычно CSS не является ключевой областью исследований, но на самом деле это связано с отсутствием внимания к CSS в отечественной отрасли, и не так много команд и талантов, которые действительно опытны и сосредоточены на CSS. Поэтому, если у вас есть собственное понимание и опыт в области CSS, это будет немалым плюсом и выделится.
JavaScript
1. Прототип/Конструктор/Экземпляр
-
прототип
(prototype): простой объект, который реализуетнаследование имущества. Его можно просто понимать как отца объекта. В Firefox и Chrome каждыйJavaScriptобъект содержит__proto__Свойство (нестандартное) указывает на своего родителя (прототип объекта), который может бытьobj.__proto__получить доступ. -
Конструктор: можно передать
newПриходитьсоздать новый объектФункция. -
Пример: Через конструктор и
newСозданный объект является экземпляром.экземпляр передан__proto__указать на прототип, черезconstructorуказать на конструктор.
После долгих разговоров все могут немного растеряться, вот каштан,ObjectНапример, мы обычно используемObjectявляется конструктором, поэтому мы можем создавать экземпляры из него.
// 实例
const instance = new Object()
Тогда в это время,Примерinstance, КонструкторObject, мы знаем, что конструктор имеетprototypeсвойство указывает на прототип, поэтому прототип:
// 原型
const prototype = Object.prototype
Здесь мы можем увидеть взаимосвязь между тремя:
实例.__proto__ === 原型
原型.constructor === 构造函数
构造函数.prototype === 原型
// 这条线其实是是基于原型进行获取的,可以理解成一条基于原型的映射线
// 例如:
// const o = new Object()
// o.constructor === Object --> true
// o.__proto__ = null;
// o.constructor === Object --> false
// 注意: 其实实例上并不是真正有 constructor 这个指针,它其实是从原型链上获取的
// instance.hasOwnProperty('constructor') === false (感谢 刘博海 Brian 童鞋🥳)
实例.constructor === 构造函数
Спасибо детской обуви caihaihong за указание.
Увеличив масштаб, я нарисовал картинку для вашего полного понимания:
2. Цепь прототипа:
Цепочка прототипов состоит из объектов-прототипов., каждый объект имеет__proto__свойство, указывающее на прототип конструктора, создавшего объект,__proto__Соединение объектов вместе образует цепочку прототипов. используетсяРеализовать наследование и общие свойстваконечная цепочка объектов.
-
механизм поиска свойств: При поиске атрибута объекта, если сам экземпляр объекта не имеет атрибута, он будет искать один уровень вверх по цепочке прототипов. Если он найден, он будет выведен. Если он не существует, он будет продолжить поиск на один уровень вверх по цепочке прототипов, пока не появится объект-прототип верхнего уровня.
Object.prototype, если все еще не найдено, выведитеundefined; -
механизм изменения свойства: Будут изменены только свойства самого экземпляра объекта.Если он не существует, свойства будут добавлены.Если вам нужно изменить свойства прототипа, вы можете использовать:
b.prototype.x = 2; но это приведет к изменению свойств всех экземпляров, наследуемых от этого объекта.
3. Контекст выполнения (EC)
Контекст выполнения можно просто понимать как объект:
-
Он состоит из трех частей:
- Переменный объект (VO)
- цепочка областей видимости (лексическая область видимости)
-
thisнаправление
-
его тип:
- глобальный контекст выполнения
- контекст выполнения функции
-
evalконтекст выполнения
-
Процесс выполнения кода:
- Создайтеглобальный контекст (global EC)
- Глобальный контекст выполнения (вызывающий) построчносверху внизвоплощать в жизнь. При встрече с функциейконтекст выполнения функции(вызываемый) быть
pushна вершину стека выполнения - Активируется контекст выполнения функции, становится активным EC, начинается выполнение кода в функции, а вызывающая программа приостанавливается.
- После выполнения функции вызывается callee
popУдалите стек выполнения, верните управление глобальному контексту (вызывающему объекту) и продолжите выполнение.
2. Переменный объект
Переменные объекты, которые являются частью контекста выполнения, могут быть абстрагированы какобъем данных, по сути, его можно понимать и как простой объект, в котором хранятся всеОбъявления переменных и функций (за исключением функциональных выражений).
Активный объект (AO): Когда контекст, в котором находится переменный объект, является активным EC, он называется активным объектом.
3. Объем
Контекст выполнения также содержит цепочку областей видимости. Прежде чем понять масштаб, давайте представим его. Область действия фактически может быть понята как объявление в контекстеОбласть видимости переменных и объявлений. Его можно разделить наобласть блокаа такжеобъем функции
характеристика:
- заявление заранее: объявление видно внутри тела функции, функции имеют приоритет над переменными
- Неанонимная самовыполняющаяся функция, переменная функциитолько чтениестатус, не может быть изменен
let foo = function() { console.log(1) };
(function foo() {
foo = 10 // 由于foo在函数中只为可读,因此赋值无效
console.log(foo)
}())
// 结果打印: ƒ foo() { foo = 10 ; console.log(foo) }
4. Цепочка областей
Мы знаем, что можем получить доступ к родительским или даже глобальным переменным в контексте выполнения, и именно здесь вступает в действие цепочка областей видимости. Цепочку областей действия можно понимать как список объектов, в том числеродительские и собственные переменные объекты, поэтому мы можем получить доступ к переменным или функциям, объявленным в родительском элементе, через цепочку областей видимости.
- Состоит из двух частей:
-
[[scope]]Атрибут: указывает на родительский объект переменной и цепочку областей, то есть содержит родительский объект.[[scope]]а такжеAO - АО: собственный объект деятельности
-
этим способом[[scopr]]Включать[[scope]], образуя линию сверху внизЦепочка областей.
5. Закрытие
Замыкания относятся к особому типу области видимости, называемойстатическая область. Его определение можно понимать как:Родительская функция уничтоженаВ случае возвращаемой подфункции[[scope]]Родительский объект с одной переменной и цепочка областей действия по-прежнему сохраняются в , поэтому вы можете продолжать получать доступ к родительскому объекту переменной.Такая функция называется замыканием.
-
Замыкания создают классическую проблему:
- нескольких подфункций
[[scope]]Оба указывают на родителя одновременно и являются полностью общими. Таким образом, когда изменяемый объект родительского объекта изменяется, затрагиваются все дочерние функции.
- нескольких подфункций
-
решить:
- переменные могут бытьФорма параметра функциипередано, избегайте использования значения по умолчанию
[[scope]]Погляди - использовать
setTimeoutпакет, переданный в качестве третьего параметра - использоватьобласть действия блока, сделайте переменную свойством своего собственного контекста, чтобы избежать совместного использования
- переменные могут бытьФорма параметра функциипередано, избегайте использования значения по умолчанию
6. Метод внедрения сценария:
- html статический
<script>представлять - js динамическая вставка
<script> -
<script defer>: отложенная загрузка, выполняемая после завершения синтаксического анализа элемента -
<script async>: загружать асинхронно, но блокировать рендеринг элемента при выполнении
7. Копии объектов
-
Поверхностная копия: скопируйте эталонный объект в виде присвоения, по-прежнему указывая на тот же адрес,Исходный объект также изменяется при изменении
Object.assign- оператор спреда(...)
-
Глубокая копия: полностью скопировать новый объект,Исходный объект больше не подвергается никаким изменениям
-
JSON.parse(JSON.stringify(obj)): Самая быстрая производительность- Когда объект имеет циклическую ссылку, сообщается об ошибке
- Когда значение является функцией,
undefined,илиsymbolнельзя скопировать
- Рекурсивно назначать один за другим
-
8. Процесс выполнения нового оператора
- создать новый объект
- Ссылка на прототип:
obj.__proto__ = Con.prototype - привязать это:
apply - Возвращает новый объект (если конструктор имеет собственный повтор, возвращается это значение)
9. Принцип instanceof
в случаецепочка объектов прототипанайти конструктор вprototypeатрибут указывает напрототип объекта, просто вернисьtrue. который:
// __proto__: 代表原型对象链
instance.[__proto__...] === instance.constructor.prototype
// return true
10. Повторное использование кода
Когда вы обнаружите, что какой-либо код пишется во второй раз, начните думать о том, как его повторно использовать. Как правило, существуют следующие способы:
- инкапсуляция функций
- наследовать
- копировать
extend - смешать
mixin - занимать
apply/call
11. Наследование
В JS наследование обычно относится кНаследование цепочки прототипов, то есть путем указания прототипа и наследования свойств или методов прототипа через цепочку прототипов.
- оптимизировать:Режим Святого Грааля
var inherit = (function(c,p){
var F = function(){};
return function(c,p){
F.prototype = p.prototype;
c.prototype = new F();
c.uber = p.prototype;
c.prototype.constructor = c;
}
})();
- Синтаксический сахар с использованием ES6
class / extends
12. Преобразование типов
Всем известно, что при использовании символов операторов или контрастных символов в JS будут неявные преобразования, правила таковы:
- -, *, /, %: все преобразовано в числовые значения и рассчитано
- +:
- число + строка = строка, порядок операций слева направо
- число + объект, первым вызывается один из объектов
valueOf->toString - номер +
boolean/null-> число - номер +
undefined->NaN
[1].toString() === '1'{}.toString() === '[object object]'-
NaN!==NaN,+undefined 为 NaN
13. Типовая оценка
Судя по типу Target, только typeof не может его полностью удовлетворить Это не баг Существенная причина в теории JS о том, что все является объектом. Таким образом, чтобы действительно сделать правильные суждения, нам нужно различать:
- основной тип(
null): использоватьString(null) - основной тип(
string / number / boolean / undefined) +function: Использовать напрямуюtypeofТолько что - остальные ссылочные типы (
Array / Date / RegExp Error): передачаtoStringпозже согласно[object XXX]судить
Очень стабильный пакет суждений:
let class2type = {}
'Array Date RegExp Object Error'.split(' ').forEach(e => class2type[ '[object ' + e + ']' ] = e.toLowerCase())
function type(obj) {
if (obj == null) return String(obj)
return typeof obj === 'object' ? class2type[ Object.prototype.toString.call(obj) ] || 'object' : typeof obj
}
14. Модульный
Модульная разработка — неотъемлемая часть современной разработки, которая значительно улучшает ремонтопригодность, масштабируемость и совместную работу над проектами. Обычно мыИспользуйте модульную поддержку ES6 в браузере и модульную поддержку commonjs в Node.
-
Классификация:
- es6:
import / export - commonjs:
require / module.exports / exports - amd:
require / defined
- es6:
-
requireа такжеimportразница-
requireслужба поддержкидинамический импорт,importНе поддерживается, в предложении (поддерживается в Babel) -
requireдаСинхронизироватьимпорт,importпринадлежатьасинхронныйимпорт -
requireдакопия значения, изменение экспортируемого значения не повлияет на импортированное значение;importнаправлениеадрес памяти, значение импорта изменится со значением экспорта
-
15. Защита от сотрясений и дросселирование
Функция защиты от сотрясений и дроссельной заслонки является одной из наиболее часто используемых.Метод оптимизации высокочастотного триггера, что может значительно повысить производительность.
- опровергать: Оптимизируйте несколько высокочастотных операций, которые будут выполняться только в последний раз.Обычно используемый сценарий: пользовательский ввод, нужно только выполнить проверку ввода после завершения ввода.
function debounce(fn, wait, immediate) {
let timer = null
return function() {
let args = arguments
let context = this
if (immediate && !timer) {
fn.apply(context, args)
}
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(context, args)
}, wait)
}
}
- дроссель: Выполняется через определенный период времени, то есть для уменьшения частоты и оптимизации высокочастотной операции в низкочастотную операцию, обычно используется в сценарии: событие полосы прокрутки или событие изменения размера, обычно выполняется один раз каждые 100~500 РС.
function throttle(fn, wait, immediate) {
let timer = null
let callNow = immediate
return function() {
let context = this,
args = arguments
if (callNow) {
fn.apply(context, args)
callNow = false
}
if (!timer) {
timer = setTimeout(() => {
fn.apply(context, args)
timer = null
}, wait)
}
}
}
16. Выполнение функции меняет это
Из-за принципа разработки JS: в функции вы можете ссылаться на переменные в среде выполнения. Следовательно, необходим механизм, позволяющий нам получить текущую рабочую среду внутри тела функции, котораяthis.
Так что поймиthisУказание, по сути, заключается в том, чтобы выяснить среду выполнения функции, которая вызывает функцию. Например:
-
obj.fn(), то естьobjФункция вызывается, то есть в функцииthis === obj -
fn(), здесь можно увидеть какwindow.fn(),следовательноthis === window
Но этот механизм не полностью отвечает потребностям нашего бизнеса, поэтому есть три способа вручную изменитьthisуказывает на:
call: fn.call(target, 1, 2)apply: fn.apply(target, [1, 2])bind: fn.bind(target)(1,2)
17. ES6/ES7
Благодаря мощи и популярности Babel, ES6/ES7 в настоящее время просто необходимы для современной разработки. С новым синтаксическим сахаром весь код можно сделать более кратким и удобным для чтения.
-
утверждение
-
let / const: область действия на уровне блоков, без продвижения переменных, временная мертвая зона, без повторных объявлений -
const: объявляет константы, не может быть изменен
-
-
присваивание деструктуризации
-
class / extend: Объявление класса и наследование -
Set / Map: новая структура данных -
Асинхронное решение:
-
Promiseиспользование и реализация -
generator:-
yield: код паузы -
next(): продолжить выполнение кода
-
function* helloWorld() { yield 'hello'; yield 'world'; return 'ending'; } const generator = helloWorld(); generator.next() // { value: 'hello', done: false } generator.next() // { value: 'world', done: false } generator.next() // { value: 'ending', done: true } generator.next() // { value: undefined, done: true }-
await / async: Даgeneratorсинтаксический сахар, вавилон основан наpromiseвыполнить.
async function getUserByAsync(){ let user = await fetchUser(); return user; } const user = await getUserByAsync() console.log(user) -
18. AST
Абстрактное синтаксическое дерево, который разбирается кодовое письмо по букве вОбъект дереваформа. Это основа для преобразования между языками, проверки синтаксиса кода, проверки стиля кода, форматирования кода, выделения кода, подсказок об ошибках кода, автоматического завершения кода и многого другого. Например:
function square(n){
return n * n
}
Преобразовано в путем синтаксического анализаASTКак показано ниже:
19. принцип компиляции babel
- Babylon анализирует код ES6/ES7 в AST
- babel-traverse проходит и транслирует AST, чтобы получить новый AST
- Новый AST конвертируется в ES5 через babel-генератор
20. Каррирование функций
Техника сначала заполнения нескольких параметров в функции, а затем возврата новой функции называется каррированием функции. Обычно может использоваться для написания функций для функций без вторжения в них.Предустановленные общие параметры, для нескольких повторных вызовов.
const add = function add(x) {
return function (y) {
return x + y
}
}
const add1 = add(1)
add1(2) === 3
add1(20) === 21
21. Массив (массив)
-
map: пройтись по массиву и вернуть новый массив, состоящий из возвращаемого значения обратного вызова -
forEach: не можемbreak,Можно использоватьtry/catchсерединаthrow new Errorостановиться -
filter: фильтр -
some: Возвращен один товарtrue, то целоеtrue -
every: Возвращен один товарfalse, то целоеfalse -
join: создать строку, указав конкатенатор -
push / pop: нажмите и вытолкните в конце, изменив исходный массив,pushвозвращает длину массива,popВозвращает последний элемент исходного массива; -
unshift / shift: Головка толкается и выталкивается, изменяя исходный массив,unshiftвозвращает длину массива,shiftВернуть первый элемент исходного массива; -
sort(fn) / reverse: Сортировка и реверсирование, изменение исходного массива -
concat: Объединение массивов, не влияет на исходный массив, неглубокая копия. -
slice(start, end): возвращает новый усеченный массив без изменения исходного массива. -
splice(start, number, value...): возвращает массив, состоящий из удаленных элементов, значением является вставленный элемент, и изменяет исходный массив. -
indexOf / lastIndexOf(value, fromIndex): найти элемент массива и вернуть соответствующий индекс -
reduce / reduceRight(fn(prev, cur), defaultPrev): Два два выполнения, предыдущая функция последней оценкиreturnзначение, cur - текущее значение- при входящем
defaultPrev, начать с первого элемента; - Если не передано, второй элемент
- при входящем
-
Массив не по порядку:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.sort(function () {
return Math.random() - 0.5;
});
- Разрушение массива: flat: [1,[2,3]] --> [1, 2, 3]
Array.prototype.flat = function() {
return this.toString().split(',').map(item => +item )
}
браузер
1. Перекрестная коммуникация
Важным принципом связи между различными вкладками является использование некоторыхобщий посредник, поэтому чаще всего используются следующие методы:
-
через родительскую страницу
window.open()и подстраницыpostMessage- Асинхронно, через
window.open('about: blank')а такжеtab.location.href = '*'
- Асинхронно, через
-
Установить общий доступ в том же домене
localStorageс мониторингомwindow.onstorage- Повторная запись одного и того же значения не срабатывает
- Будет ограничено режимом инкогнито браузера и т. д.
-
Настроить общий доступ
cookieс постоянным опросом на наличие грязных проверок (setInterval) -
Реализуется сервером или средним уровнем
2. Архитектура браузера
- Пользовательский интерфейс
- основной процесс
- ядро
- движок рендеринга
- JS-движок
- стек выполнения
- поток триггера события
- очередь сообщений
- микрозадачи
- задача макроса
- очередь сообщений
- сетевой асинхронный поток
- поток таймера
3. Цикл событий браузера (Цикл событий)
Цикл событий означает: выполнить задачу макроса, затем выполнить, чтобы очистить список микрозадач, зациклиться и снова выполнить задачу макроса, а затем очистить список микрозадач.
- микрозадачи
microtask(jobs):promise / ajax / Object.observe(该方法已废弃) - задача макроса
macrotask(task):setTimout / script / IO / UI Rendering
4. Процесс от ввода URL до отображения
- разрешение DNS
- Трехстороннее рукопожатие TCP
- Отправить запрос, проанализировать URL, установить сообщение запроса (заголовок, тело)
- Сервер возвращает запрошенный файл (html)
- рендеринг в браузере
- HTML parser --> DOM Tree
- Алгоритм токенизации для маркировки состояний элементов
- строительство дома из дерева
- CSS parser --> Style Tree
- Разобрать код css и создать дерево стилей
- attachment --> Render Tree
- Объедините дерево домов и дерево стилей для создания дерева рендеринга.
- макет: макет
- Рисование с помощью графического процессора: страница рисования пикселей
- HTML parser --> DOM Tree
5. Перерисовка и перекомпоновка
Когда стиль элемента изменяется, браузер должен инициировать обновление, перерисовывая элемент. В этом процессе есть два типа операций, а именно перерисовка и перекомпоновка.
-
перекрашивать: когда изменение стиля элемента не влияет на макет, браузер будет использовать перерисовку для обновления элемента.В настоящее время требуется только перерисовка пикселей на уровне пользовательского интерфейса, поэтомуменьше потерь
-
переплавка: Браузер перерисовывает страницу, когда активируются размер, структура или определенные свойства элемента, что называется перекомпоновкой. В это время браузеру необходимо произвести перерасчет, а после расчета ему необходимо переразметить страницу, так что это более тяжелая операция. Действия, вызывающие перекомпоновку:
- Первый рендер страницы
- Изменение размера окна браузера
- Размер элемента, положение, содержимое изменены
- Изменение размера шрифта элемента
- Добавить или удалить видимые элементы dom
- Активировать псевдоклассы CSS (например: :hover)
- запрашивать определенные свойства или вызывать определенные методы
- clientWidth, clientHeight, clientTop, clientLeft
- offsetWidth, offsetHeight, offsetTop, offsetLeft
- scrollWidth, scrollHeight, scrollTop, scrollLeft
- getComputedStyle()
- getBoundingClientRect()
- scrollTo()
Перекомпоновка должна запускать перерисовку, а перерисовка не обязательно запускает перерисовку. Накладные расходы на перерисовку невелики, а стоимость оплавления высока.
Лучшие практики:
-
css
- избегать использования
tableмакет - Применение анимационных эффектов к
positionсобственностьabsoluteилиfixedна элементе
- избегать использования
-
javascript
- Избегайте частых манипуляций со стилями, которые можно консолидировать и унифицировать.одна модификация
- использовать как можно больше
classВнесите изменения в стиль - уменьшать
domМожно использовать количество добавлений и удаленийнитьилиdocumentFragmentодноразовая вставка - При экстремальной оптимизации измените стиль, чтобы он
display: noneпост модификация - Избегайте запуска вышеупомянутых методов, которые несколько раз запускают перекомпоновку, и старайтесь использовать их, если это возможно.переменные сохраняются
6. Хранение
Нам часто нужно хранить некоторые данные в бизнесе, которые обычно можно разделить на временное хранилище и постоянное хранилище.
-
Когда это эфемерно, нам нужно только хранить данные в памяти, доступной только во время выполнения.
-
Постоянное хранилище можно разделить на сторону браузера и сторону сервера.
- Браузер:
-
cookie: обычно используется для хранения идентификатора пользователя, статуса входа и т. д.- Автоматически переносится в http, верхний предел объема 4K, а время истечения можно установить самостоятельно
-
localStorage / sessionStorage: долговременное хранение/закрытие и удаление окна, ограничение объема 4~5M indexDB
-
- сервер:
- Распределенный кеш
- база данных
- Браузер:
7. Web Worker
Современные браузерыJavaScriptтворческиймногопоточная среда. Может создавать новые и назначать некоторые задачиworkerПотоки работают параллельно, два потока могутНезависимая работа, не мешая друг другу, через встроенныймеханизм сообщенияобщаться друг с другом.
Основное использование:
// 创建 worker
const worker = new Worker('work.js');
// 向 worker 线程推送消息
worker.postMessage('Hello World');
// 监听 worker 线程发送过来的消息
worker.onmessage = function (event) {
console.log('Received message ' + event.data);
}
предел:
- ограничение гомологии
- Недоступно
document/window/alert/confirm - Не удалось загрузить локальный ресурс
8. Механизм сборки мусора V8
Сборка мусора: очищайте данные, которые больше не используются в памяти, чтобы освободить место в памяти. V8 делит память наКайнозойское пространствоа такжепространство старого поколения.
-
Кайнозойское пространство: для недолговечных объектов
- Он разделен на два пространства: из космоса и в космос
- Алгоритм Scavenge GC: когда пространство from заполнено, запустите алгоритм GC
- Живые объекты перемещаются из космоса в космос
- пустой из космоса
- из космоса и в космос взаимозаменяемы
- Комплектация ГХ нового поколения
-
пространство старого поколения: для объектов, которые живут дольше
- Условия перехода из пространства молодого поколения в пространство старого поколения
- Объекты, прошедшие более одного GC Scavenge GC
- Когда объем пространства превышает 25%
-
Алгоритм развертки пометки: Отмечать живые объекты, неотмеченные объекты освобождаются
- Инкрементные маркеры: небольшие маркеры модулей, выполняемые между выполнениями кода, GC повлияет на производительность.
- Маркировка параллелизма (новейшая технология): не блокирует выполнение js
- алгоритм сжатия: переместите фрагментированные объекты, вызванные очисткой памяти, в один конец кучи памяти, чтобы решить проблему.Фрагментация памяти
- Условия перехода из пространства молодого поколения в пространство старого поколения
9. Утечка памяти
- Непредвиденныйглобальная переменная: не может быть переработан
- таймер: не закрыто должным образом, в результате чего указанная внешняя переменная не может быть освобождена
- прослушиватель событий: неправильно уничтожается (может появиться в браузерах более ранних версий)
- Закрытие: приведет к тому, что переменная в родительском элементе не будет освобождена
- ссылка на дом: ссылки в памяти не очищались должным образом при удалении элемента dom.
Вы можете использовать временную шкалу в Chrome, чтобы отметить память, визуализировать изменения в памяти и найти выбросы.
Сервер и сеть
1. протокол http/https
-
1.0 Недостатки протокола:
- Ссылка не может быть использована повторно, и после завершения она будет отключена.Перезапустите медленный старт и трехстороннее рукопожатие TCP
- head of line blocking: Блокировка потока, заставляя запросы взаимодействовать друг с другом
-
1.1 Улучшения:
- Длинное соединение(поддержание активности по умолчанию), повторное использование
- Поле host указывает соответствующий виртуальный сайт
- новые особенности:
- http
- Аутентификация
- государственное управление
- кеш-кэш
- Cache-Control
- Expires
- Last-Modified
- Etag
-
2.0:
- мультиплексирование
- Двоичный уровень кадрирования: между прикладным уровнем и транспортным уровнем
- сжатие заголовка
- Пуш сервера
-
https: более безопасный протокол сетевой передачи
- сертификат (открытый ключ)
- SSL-шифрование
- порт 443
-
TCP:
- трехстороннее рукопожатие
- помахал четыре раза
- Скользящее окно: управление потоком
- обработка перегрузок
- медленный старт
- предотвращение перегрузки
- быстрая ретрансляция
- быстрое восстановление
-
Стратегия кэширования: можно разделить наСильный кеша такжеСогласовать кеш
-
Cache-Control/Expires: Браузер определяет, истек ли срок действия кеша, и если он еще не истек, он напрямую использует сильный кеш.Максимальный возраст Cache-Control имеет приоритет над Expires
-
Когда срок действия кеша истек, используйте согласованный кеш
- Уникальная схема идентификации: Etag (передается ответом) и If-None-Match (передается запросом, Etag возвращается в последний раз): сервер определяет, был ли изменен ресурс.
- Время последнего изменения: Last-Modified (ответ) и If-Modified-Since (запрос, последнее изменение Last-Modified возвращено)
- Если это соответствует, верните 304 напрямую, чтобы уведомить браузер о необходимости использования кеша.
- В случае несоответствия сервер возвращает новый ресурс
-
Недостатки последней модификации:
- Периодическая модификация, но когда содержимое не меняется, это приведет к аннулированию кеша.
- Минимальная степень детализации — только s, и изменения внутри s не могут быть обнаружены.
-
Etag имеет приоритет над Last-Modified
-
2. Общие коды состояния
- 1xx: принять, продолжить обработку
- 200: успех и возврат данных
- 201: создан
- 202: Принято
- 203: Стать, но не авторизоваться
- 204: успех, нет содержимого
- 205: успех, сброс содержимого
- 206: Успех, часть содержания
- 301: Переместить навсегда, перенаправить
- 302: временное перемещение, можно использовать исходный URI.
- 304: Ресурс не изменен, кеш можно использовать
- 305: требуется доступ через прокси
- 400: Ошибка синтаксиса запроса
- 401: требуется аутентификация
- 403: запрос отклонен
- 404: Ресурс не существует
- 500: Ошибка сервера
3. get / post
- get: кеш, длина запроса ограничена, будет записано в историю
- Без побочных эффектов (без модификации ресурса), идемпотентный (количество запросов не имеет ничего общего с ресурсом) сценарии
- сообщение: безопасность, большие данные, дополнительные типы кодирования
Подробное сравнение этих двух средств выглядит следующим образом:
4. Websocket
Веб-сокет — этопостоянный протокол, на основе http сервер можетАктивный толчок
-
совместимый:
- FLASH Socket
- Длинный опрос: регулярно отправлять ajax
- длинный опрос: отправить --> ответить, когда есть сообщение
-
new WebSocket(url) -
ws.onerror = fn -
ws.onclose = fn -
ws.onopen = fn -
ws.onmessage = fn -
ws.send()
5. Трехстороннее рукопожатие TCP
Перед установкой соединения клиент и сервер должны подтвердить друг друга через рукопожатие:
- Клиент отправляет запрос на синхронизацию (порядковый номер синхронизации), переходит в состояние syn_send и ожидает подтверждения.
- После получения и подтверждения пакета syn сервер отправляет пакет syn+ack и переходит в состояние syn_recv.
- После того, как клиент получает пакет syn+ack, он отправляет пакет подтверждения, и обе стороны переходят в установленное состояние.
6. ПТС махнул четыре раза
- Клиент -- FIN --> Сервер, FIN -- ПОДОЖДИТЕ
- Сервер -- ACK --> Клиент, ЗАКРЫТЬ-ЖДАТЬ
- Сервер -- ACK, FIN --> Клиент, LAST-ACK
- Клиент -- ACK --> Сервер, ЗАКРЫТ
7. Цикл событий узла: 6 этапов
- фаза таймера: выполнение истекло
setTimeout / setIntervalобратный вызов очереди - Фаза ввода-вывода: выполнение последнего цикла остаточного потока цикла.
callback - idle, prepare
- опрос: дождитесь обратного звонка
-
- выполнить обратный вызов
-
- выполнение таймера
- если истек
setTimeout / setInterval, затем вернитесь к этапу таймера - если есть
setImmediate, затем перейти к этапу проверки
-
- check
- воплощать в жизнь
setImmediate
- воплощать в жизнь
- close callbacks
перекрестный домен
- JSONP: эксплойт
<script>На тег не распространяются междоменные ограничения, недостатком является то, что он может поддерживать только запросы на получение.
function jsonp(url, jsonpCallback, success) {
const script = document.createElement('script')
script.src = url
script.async = true
script.type = 'text/javascript'
window[jsonpCallback] = function(data) {
success && success(data)
}
document.body.appendChild(script)
}
- Установите CORS: Access-Control-Allow-Origin: *
- postMessage
Безопасность
- XSS-атака: внедрение вредоносного кода
- настройка куки httpOnly
- Экранирование ввода и вывода на странице
- CSRF: подделка межсайтовых запросов, защита:
- get не изменяет данные
- Файлы cookie пользователя не доступны сторонним веб-сайтам.
- Настройте белый список, чтобы избежать запросов сторонних веб-сайтов
- запросить подтверждение
Фреймворк: Vue
1. nextTick
в следующий разdomВыполните отложенный обратный вызов после завершения цикла обновления, который можно использовать для получения обновленногоdomусловие
-
По умолчанию в новой версии
microtasks,v-onбудет использоваться вmacrotasks -
macrotasksРеализация задачи:setImmediate / MessageChannel / setTimeout
2. Жизненный цикл
-
_init_-
initLifecycle/Event,ПрошлоеvmМонтировать различные свойства на -
callHook: beforeCreated: экземпляр только что создан -
initInjection/initState: Инициализация инъекции и реагирования на данные -
created: Создание завершено, свойство привязано, но настоящее еще не сгенерированоdom - Установите элемент:
$el / vm.$mount() - Здесь
template: разобрано наrender function-
*.vueдокумент:vue-loaderбудет<template>скомпилировано вrender function
-
-
beforeMount: перед компиляцией/монтированием шаблона - воплощать в жизнь
render function, генерируя реальныйdom, и заменить наdom treeсередина -
mounted: компонент смонтирован
-
-
update:- воплощать в жизнь
diffАлгоритм сравнения того, должны ли изменения запускать обновление пользовательского интерфейса -
flushScheduleQueue-
watcher.before: вызыватьbeforeUpdateкрюк -watcher.run(): воплощать в жизньwatcherсерединаnotify, уведомить все зависимости для обновления пользовательского интерфейса
-
- вызывать
updatedхук: компонент обновлен
- воплощать в жизнь
-
actived / deactivated(keep-alive): Не уничтожать, не кэшировать, не активировать и не деактивировать компоненты -
destroy:-
beforeDestroy: Разрушение начинается - Уничтожить себя и рекурсивно уничтожить дочерние компоненты и прослушиватели событий
-
remove(): удалить узел -
watcher.teardown(): очистить зависимости -
vm.$off(): Отвязать монитор
-
-
destroyed: активировать хук, когда закончите
-
вышеvueПростое прочесывание цикла объявления , а потом выполним его прямо в виде кодаvueинициализация
new Vue({})
// 初始化Vue实例
function _init() {
// 挂载属性
initLifeCycle(vm)
// 初始化事件系统,钩子函数等
initEvent(vm)
// 编译slot、vnode
initRender(vm)
// 触发钩子
callHook(vm, 'beforeCreate')
// 添加inject功能
initInjection(vm)
// 完成数据响应性 props/data/watch/computed/methods
initState(vm)
// 添加 provide 功能
initProvide(vm)
// 触发钩子
callHook(vm, 'created')
// 挂载节点
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
// 挂载节点实现
function mountComponent(vm) {
// 获取 render function
if (!this.options.render) {
// template to render
// Vue.compile = compileToFunctions
let { render } = compileToFunctions()
this.options.render = render
}
// 触发钩子
callHook('beforeMounte')
// 初始化观察者
// render 渲染 vdom,
vdom = vm.render()
// update: 根据 diff 出的 patchs 挂载成真实的 dom
vm._update(vdom)
// 触发钩子
callHook(vm, 'mounted')
}
// 更新节点实现
funtion queueWatcher(watcher) {
nextTick(flushScheduleQueue)
}
// 清空队列
function flushScheduleQueue() {
// 遍历队列中所有修改
for(){
// beforeUpdate
watcher.before()
// 依赖局部更新节点
watcher.update()
callHook('updated')
}
}
// 销毁实例实现
Vue.prototype.$destory = function() {
// 触发钩子
callHook(vm, 'beforeDestory')
// 自身及子节点
remove()
// 删除依赖
watcher.teardown()
// 删除监听
vm.$off()
// 触发钩子
callHook(vm, 'destoryed')
}
3. Ответ данных (перехват данных)
Прочитав жизненный цикл, внутриwatcherи т. д. фактически являются частью ответа данных. Реализация ответа данных состоит из двух частей:наблюдатель (наблюдатель)а такжеСборщик зависимостей (Dep), ядром которого являетсяdefinePropertyэтот метод, он можетПереопределить свойство получить и установитьспособ завершения изменения данных мониторинга.
- Наблюдайте (наблюдатель) наблюдайте за реквизитом и состоянием
- Перейдите свойства и состояние и создайте отдельный слушатель ( наблюдатель ) для каждого свойства.
- использовать
definePropertyПереопределить get/set( для каждого свойстваdefineReactive)-
get: собрать зависимости-
Dep.depend()watcher.addDep()
-
-
set: Распространять обновленияDep.notify()watcher.update()queenWatcher()nextTickflushScheduleQueuewatcher.run()updateComponent()
-
Вы можете сначала посмотреть на соответствующую кодовую реализацию данных ниже, и после ее понимания вам будет легче понять простой контекст выше.
let data = {a: 1}
// 数据响应性
observe(data)
// 初始化观察者
new Watcher(data, 'name', updateComponent)
data.a = 2
// 简单表示用于数据更新后的操作
function updateComponent() {
vm._update() // patchs
}
// 监视对象
function observe(obj) {
// 遍历对象,使用 get/set 重新定义对象的每个属性值
Object.keys(obj).map(key => {
defineReactive(obj, key, obj[key])
})
}
function defineReactive(obj, k, v) {
// 递归子属性
if (type(v) == 'object') observe(v)
// 新建依赖收集器
let dep = new Dep()
// 定义get/set
Object.defineProperty(obj, k, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
// 当有获取该属性时,证明依赖于该对象,因此被添加进收集器中
if (Dep.target) {
dep.addSub(Dep.target)
}
return v
},
// 重新设置值时,触发收集器的通知机制
set: function reactiveSetter(nV) {
v = nV
dep.nofify()
},
})
}
// 依赖收集器
class Dep {
constructor() {
this.subs = []
}
addSub(sub) {
this.subs.push(sub)
}
notify() {
this.subs.map(sub => {
sub.update()
})
}
}
Dep.target = null
// 观察者
class Watcher {
constructor(obj, key, cb) {
Dep.target = this
this.cb = cb
this.obj = obj
this.key = key
this.value = obj[key]
Dep.target = null
}
addDep(Dep) {
Dep.addSub(this)
}
update() {
this.value = this.obj[this.key]
this.cb(this.value)
}
before() {
callHook('beforeUpdate')
}
}
4. Реализация принципа виртуального дома
-
создать дерево дома
-
дерево
diff, сравнение того же слоя, выводpatchs(listDiff/diffChildren/diffProps)- нет новых узлов, возврат
- новый узел
tagNameа такжеkeyбез изменений, контрастprops, продолжить рекурсивный обход поддерева- Сравните свойства (сравните старые и новые списки свойств):
- Существует ли старый атрибут в списке с новым атрибутом
- есть ли изменения
- Есть ли новые свойства, которых не было в старом списке?
- Сравните свойства (сравните старые и новые списки свойств):
-
tagNameа такжеkeyЕсли значение изменяется, оно напрямую заменяется новым узлом.
-
Различия в рендеринге
- траверс
patchs, выньте узел, который нужно изменить - локальное обновление
dom
- траверс
// diff算法的实现
function diff(oldTree, newTree) {
// 差异收集
let pathchs = {}
dfs(oldTree, newTree, 0, pathchs)
return pathchs
}
function dfs(oldNode, newNode, index, pathchs) {
let curPathchs = []
if (newNode) {
// 当新旧节点的 tagName 和 key 值完全一致时
if (oldNode.tagName === newNode.tagName && oldNode.key === newNode.key) {
// 继续比对属性差异
let props = diffProps(oldNode.props, newNode.props)
curPathchs.push({ type: 'changeProps', props })
// 递归进入下一层级的比较
diffChildrens(oldNode.children, newNode.children, index, pathchs)
} else {
// 当 tagName 或者 key 修改了后,表示已经是全新节点,无需再比
curPathchs.push({ type: 'replaceNode', node: newNode })
}
}
// 构建出整颗差异树
if (curPathchs.length) {
if(pathchs[index]){
pathchs[index] = pathchs[index].concat(curPathchs)
} else {
pathchs[index] = curPathchs
}
}
}
// 属性对比实现
function diffProps(oldProps, newProps) {
let propsPathchs = []
// 遍历新旧属性列表
// 查找删除项
// 查找修改项
// 查找新增项
forin(olaProps, (k, v) => {
if (!newProps.hasOwnProperty(k)) {
propsPathchs.push({ type: 'remove', prop: k })
} else {
if (v !== newProps[k]) {
propsPathchs.push({ type: 'change', prop: k , value: newProps[k] })
}
}
})
forin(newProps, (k, v) => {
if (!oldProps.hasOwnProperty(k)) {
propsPathchs.push({ type: 'add', prop: k, value: v })
}
})
return propsPathchs
}
// 对比子级差异
function diffChildrens(oldChild, newChild, index, pathchs) {
// 标记子级的删除/新增/移动
let { change, list } = diffList(oldChild, newChild, index, pathchs)
if (change.length) {
if (pathchs[index]) {
pathchs[index] = pathchs[index].concat(change)
} else {
pathchs[index] = change
}
}
// 根据 key 获取原本匹配的节点,进一步递归从头开始对比
oldChild.map((item, i) => {
let keyIndex = list.indexOf(item.key)
if (keyIndex) {
let node = newChild[keyIndex]
// 进一步递归对比
dfs(item, node, index, pathchs)
}
})
}
// 列表对比,主要也是根据 key 值查找匹配项
// 对比出新旧列表的新增/删除/移动
function diffList(oldList, newList, index, pathchs) {
let change = []
let list = []
const newKeys = getKey(newList)
oldList.map(v => {
if (newKeys.indexOf(v.key) > -1) {
list.push(v.key)
} else {
list.push(null)
}
})
// 标记删除
for (let i = list.length - 1; i>= 0; i--) {
if (!list[i]) {
list.splice(i, 1)
change.push({ type: 'remove', index: i })
}
}
// 标记新增和移动
newList.map((item, i) => {
const key = item.key
const index = list.indexOf(key)
if (index === -1 || key == null) {
// 新增
change.push({ type: 'add', node: item, index: i })
list.splice(i, 0, key)
} else {
// 移动
if (index !== i) {
change.push({
type: 'move',
form: index,
to: i,
})
move(list, index, i)
}
}
})
return { change, list }
}
5. Преимущества Proxy по сравнению с defineProperty
- Изменения массива также можно отслеживать
- Нет необходимости в глубоком мониторинге обхода
let data = { a: 1 }
let reactiveData = new Proxy(data, {
get: function(target, name){
// ...
},
// ...
})
6. vue-router
-
modehashhistory
- Прыгать
this.$router.push()<router-link to=""></router-link>
- заполнитель
<router-view></router-view>
7. vuex
-
state: Центр состояния -
mutations: изменить состояние -
actions: асинхронное изменение состояния -
getters: получить статус -
modules: Будуstateразделен на несколькоmodules, легко управлять
алгоритм
На самом деле алгоритм мало задействован в реальных фронтенд проектах, но все же необходимо владеть некоторыми базовыми алгоритмами.У некоторых компаний все еще есть требования и оценки на этот счет.Рекомендуется все же подготовиться немного, это бонусный вопрос.
1. Пять алгоритмов
- как дела: Локальное оптимальное решение
- Алгоритм разделяй и властвуй: Разделено на несколько небольших модулей, как и исходная задача.
- динамическое программирование: Каждое состояние представляет собой сводку прошлой истории
- Возвращение: когда первоначальный выбор окажется неподходящим, вернитесь и выберите снова.
- метод ветвей и границ
2. Базовый алгоритм сортировки
- Пузырьковая сортировка: попарное сравнение
function bubleSort(arr) {
var len = arr.length;
for (let outer = len ; outer >= 2; outer--) {
for(let inner = 0; inner <=outer - 1; inner++) {
if(arr[inner] > arr[inner + 1]) {
[arr[inner],arr[inner+1]] = [arr[inner+1],arr[inner]]
}
}
}
return arr;
}
- Сортировка выбором: обход элементов после себя, и самый маленький элемент меняет местами с самим собой
function selectSort(arr) {
var len = arr.length;
for(let i = 0 ;i < len - 1; i++) {
for(let j = i ; j<len; j++) {
if(arr[j] < arr[i]) {
[arr[i],arr[j]] = [arr[j],arr[i]];
}
}
}
return arr
}
- Сортировка вставками: вставка элементов в отсортированный массив
function insertSort(arr) {
for(let i = 1; i < arr.length; i++) { //外循环从1开始,默认arr[0]是有序段
for(let j = i; j > 0; j--) { //j = i,将arr[j]依次插入有序段中
if(arr[j] < arr[j-1]) {
[arr[j],arr[j-1]] = [arr[j-1],arr[j]];
} else {
break;
}
}
}
return arr;
}
3. Расширенные алгоритмы сортировки
- быстрая сортировка
- Выберите базовое значение (база), уменьшите длину исходного массива на единицу (базовое значение), используйте склейку
- Зациклите исходный массив, поместите меньший слева (левый массив) и поместите большой справа (правый массив);
- concat(left, base, right)
- Рекурсивно продолжить сортировку слева и справа
function quickSort(arr) {
if(arr.length <= 1) {
return arr; //递归出口
}
var left = [],
right = [],
current = arr.splice(0,1);
for(let i = 0; i < arr.length; i++) {
if(arr[i] < current) {
left.push(arr[i]) //放在左边
} else {
right.push(arr[i]) //放在右边
}
}
return quickSort(left).concat(current,quickSort(right));
}
-
Сортировка по холму: сортировка вставками с неопределенным количеством шагов, сортировка вставками
-
Формула: вставка риска и возврат в базу стабильна, а быстрый подбор нестабилен.
Стабильность: может ли позиция обмениваться под тот же размер, а нестабильность diff виртуального дома приведет к повторному рендерингу;
4. Рекурсивное использование (последовательность Фибоначчи): задача о подъеме по лестнице.
Изначально на первом уровне есть один путь на первый уровень (s(1) = 1), и только один путь на второй уровень (s(2) = 1), а на третий уровень (s(3) ) = с (1) + с (2))
function cStairs(n) {
if(n === 1 || n === 2) {
return 1;
} else {
return cStairs(n-1) + cStairs(n-2)
}
}
5. Дерево данных
- Бинарное дерево: имеет не более двух детей
- полное бинарное дерево
- полное бинарное дерево
- Глубина равна h, имеется n узлов и n = 2^h - 1.
- Двоичное дерево поиска: это специальное двоичное дерево, которое может эффективно повысить эффективность поиска.
- Маленькие значения слева, большие значения справа
- Все значения левого поддерева узла n меньше n, а все значения правого поддерева больше n
- узлы траверсы
- обход предварительного заказа
-
- корневой узел
-
- посетить левого ребенка, вернуться к 1
-
- посетите нужного ребенка, вернитесь к 1
-
- Неупорядоченный обход
-
- Сначала посетите крайний левый дочерний узел
-
- посетить родительский узел этого узла
-
- посетите правый дочерний элемент родительского узла, вернитесь к 1
-
- пост-порядковый обход
-
- Сначала посетите крайний левый дочерний узел
-
- посетить соседний правый узел
-
- посетить родительский узел, вернуться к 1
-
- обход предварительного заказа
- Вставка и удаление узлов
6. Найдите неисправные балансы
Есть n монет, одна из которых фальшивая. Фальшивые монеты легче по весу. У вас есть весы. Извините, сколько раз нужно хотя бы взвесить, чтобы убедиться, что фальшивые монеты найдены?
- Алгоритм трисекции:
-
- Разделите монеты на 3 группы, возьмите любые две группы и взвесьте их на весах.
- Баланс, фальшивая валюта находится в группе, которая не взвешивается, сбросить ее на 1 и продолжить цикл
- Неуравновешенный, контрафакт легче на балансе, верните его в 1 и продолжите цикл
-
Эпилог
Из-за ограниченности энергии, времени и места эта статья будет написана здесь первой. Всем не торопитесь. . 🤪. В следующей главе я планирую подготовить следующий контент, и сначала мне нужно составить уроки:
- Связанные с веб-пакетом
- принцип
- Loader
- Plugin
- Оптимизация производительности проекта
- Оптимизация рендеринга первого экрана
- Оптимизация пользовательского опыта
- оптимизация производительности веб-пакета
- Гибрид и веб-просмотр
- процесс загрузки веб-просмотра
- принцип моста
- гибридное приложение
- Фреймворк: Реагировать
Из-за ограниченности энергии, времени и места эта статья будет написана здесь первой. Всем не торопитесь. . 🤪. Настройте свой разум и продолжайте
В интервью нет реальных ответов во многих областях, и глубина ответа зависит от вашего собственного использования и исследования. Широта и глубина знаний должны идти рука об руку, постарайтесь расширить свою область, по крайней мере, иметь некоторое базовое понимание, вы можете общаться с интервьюером, когда его спросят, а затем иметь достаточную глубину в вашей любимой области. интервьюер чувствует, что вы эксперт в этой области.
Схема знаний все еще совершенствуется и пересматривается.Поскольку энергия и время ограничены, я постепенно добавлю части, перечисленные позже. Конечно, я также постоянно учусь в процессе разбора, и я надеюсь, что все смогут принять участие вместе.Если вам нужно что-то добавить или пересмотреть, пожалуйста, быстро поднимайте его. Кроме того, я только что создал новый официальный аккаунт. Я хочу использовать его как место для общения и обмена информацией. Детская обувь, которая интересуется идеями, может связаться со мной ~~😉
Советы: Свяжитесь со мной по почте 159042708@qq.com или QQ/WeChat: 159042708.
Блогер очень жестко написала, спасибо за накрутку звездаgithub. 😚