Недавно я увидел статью, в которой резюмируются некоторые вопросы для фронтенд-интервью. Целью должен быть фронтенд среднего и среднего уровня социального рекрутинга. Я чувствую, что это имеет определенную справочную ценность. Поэтому я открыл пост, чтобы попробовать чтобы ответить на эти вопросы и, кстати, использовать их в качестве моих собственных вопросов для интервью.
Оригинальная ссылка нажмите здесь
Основы JavaScript
1. Заявить заранее о проблемах
нашел один онлайнстатья, есть вопрос на собеседовании, в котором рассматриваются многие точки знаний, включая продвижение определения переменной, указание этого указателя, приоритет оператора, прототип, наследование, загрязнение глобальной переменной, атрибут объекта и приоритет атрибута прототипа и т. д. Знания, я думаю, также очень ценны для справки:
function Foo() {
getName = function () { alert (1); };
return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}
// 请写出以下输出结果:
Foo.getName();
getName(); // 声明提前
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
Ответ на этот вопрос: 2, 4, 1, 1, 2, 3, 3.
Субъект оператора инспекции заранее отмечен в коде, и вот два оператора метода getName:
var getName = function () { alert (4) };
function getName() { alert (5) }
На самом деле именно в таком порядке при разборе:
function getName() { alert (5) }
var getName;
getName = function () { alert (4) };
Если мы добавим еще две точки останова в середине кода:
getName(); // 5
var getName = function () { alert (4) };
getName(); // 4
function getName() { alert (5) }
В первом getName и объявление функции, и объявление var помещаются перед первым getName, и операция присваивания getName не будет расширена. Простое использование объявления var не перезапишет переменную, определенную функцией. Поэтому , первым выводом getName является 5 объявления функции; Второй getName происходит после оператора присваивания, поэтому выходной результат равен 4, поэтому фактический порядок выполнения кода следующий:
function getName() { alert (5) }
var getName;
getName(); // 5
getName = function () { alert (4) };
getName(); // 4
2. Хранилище браузера
Разница между localStorage, sessionStorage и куки
Общий момент: все они хранятся на стороне браузера и доступны только из одного и того же источника.
- хранилище данных
- Данные файлов cookie всегда передаются (даже если они не нужны) в HTTP-запросах одного и того же источника, т. е. файлы cookie передаются туда и обратно между браузером и сервером. Данные cookie также имеют концепцию пути, которая может ограничить принадлежность cookie определенному пути.
- sessionStorage и localStorage не отправляют данные на сервер автоматически, а только сохраняют их локально.
- размер данных хранилища
- Ограничение размера хранилища также отличается.Данные cookie не могут превышать 4 КБ.В то же время, поскольку каждый http-запрос будет содержать cookie, cookie подходит только для хранения небольших данных, таких как идентификатор сеанса.
- Хотя sessionStorage и localStorage также имеют ограничения на размер хранилища, они намного больше файлов cookie и могут достигать 5 МБ и более.
- Срок действия хранения данных
- sessionStorage: действует только до закрытия текущего окна браузера;
- LocalStorage: всегда действителен, окно или выключение браузера также сохранено, локально сохраняется, поэтому он используется в качестве длительных данных;
- cookie: действителен только до установленного времени истечения срока действия cookie, даже если окно закрыто или браузер закрыт
- разная сфера
- sessionStorage не распределяется между разными окнами браузера, даже на одной и той же странице;
- localstorage используется во всех окнах одного и того же источника, то есть пока браузер не закрыт, данные все еще существуют.
- Файл cookie: он также используется всеми окнами одного и того же происхождения, то есть, пока браузер не закрыт, данные все еще существуют.
3. Междоменный
Вскоре я написал пост, в котором резюмировал политику единого источника и различные междоменные методы:Что такое междоменный доступ, почему браузеры запрещают междоменный доступ и к чему это приводит
4. Использование и принцип Обещания
Promise — это новая функция, добавленная в ES6, которая используется для более разумного решения проблем асинхронного программирования.Начало работы с ECMAScript 6Подробное описание сделано в , и здесь повторяться не будет.
30 минут, чтобы вы полностью поняли принцип Promise
Вышеупомянутая статья представляет собой подробное описание принципа промиса.Здесь я извлеку простейшую реализацию промиса, чтобы объяснить принцип промиса:
function Promise(fn) {
var value = null,
callbacks = []; // callbacks为数组,因为可能同时有很多个回调
this.then = function (onFulfilled) {
callbacks.push(onFulfilled);
};
function resolve(value) {
callbacks.forEach(function (callback) {
callback(value);
});
}
fn(resolve);
}
первый,then
одна или несколько функций, объявленных внутри, будут помещены вcallbacks
Список, вызываемый экземпляром Promiseresolve
Когда метод проходится и вызывается, и передается вresolve
Значение параметра, переданное в метод.
Ниже используйте простой пример для анализа процесса выполнения Promise:
functionm func () {
return new Promise(function (resolve) {
setTimeout(function () {
resolve('complete')
}, 3000);
})
}
func().then(function (res) {
console.log(res); // complete
})
func
Определение функции состоит в том, чтобы возвращать экземпляр Promise, а функция обратного вызова, передаваемая при объявлении экземпляра, добавляетresolve
параметры (этоresolve
Параметры в промисеfn(resolve)
получить определениеresolve
функциональная сущность), асинхронная операция выполняется в обратном вызове, а асинхронная операция выполняется в обратном вызове завершения асинхронной операцииresolve
функция.
Посмотрите на шаги выполнения,func
Функция возвращает экземпляр Promise, и этот экземпляр может выполнить обещание, определенное в конструкторе Promise.then
метод,then
Обратный вызов, переданный в методе, будет вresolve
(то есть после завершения асинхронной операции), тем самым реализуяthen
Метод выполняет функцию обратного вызова после завершения асинхронной операции.
5. Механизм цикла событий JavaScript
Статьи, размещенные в оригинальном тексте, имеют большую справочную ценность.Во-первых, разместите ссылку:Подробно объясните механизм цикла событий в JavaScript..
JavaScript — это однопоточный неблокирующий язык, поскольку изначально он был разработан для взаимодействия с браузерами:
- Один поток:
JavaScript
Причина, по которой он спроектирован как единый поток, заключается в том, что его основная роль в начале заключается в общении сDOM
взаимодействовать, представьте, еслиJavaScript
является многопоточным, то когда два потока одновременноDOM
Выполните действие, например добавьте к нему событие, а другое удалите этоDOM
, как бороться с этим в это время? Поэтому для того, чтобы ситуация, подобная этому примеру, не возникла,JavaScript
Выберите использование только одного основного потока для выполнения кода, чтобы обеспечить согласованность выполнения программы. - Неблокирующий: когда коду необходимо выполнить асинхронную задачу (задачу, которая не может немедленно вернуть результат и требует определенного времени для возврата, например, событие ввода-вывода), основной поток приостанавливается (
pending
) эту задачу, а затем выполнить соответствующий обратный вызов по определенным правилам, когда асинхронная задача вернет результат. а такжеJavaScript
Способ добиться асинхронной работы — использовать цикл событий.
setTimeout(function () {
console.log(1);
});
new Promise(function(resolve,reject){
console.log(2)
resolve(3)
}).then(function(val){
console.log(val);
})
Давайте разберем эту проблему через кусок кода, прежде всегоsetTimeout
а такжеPromise
серединаthen
Все обратные вызовы являются асинхронными методами, в то время какnew Promise
является синхронной операцией, поэтому этот код должен сначала немедленно вывести2
;JavaScript
Асинхронные методы делятся наmarco task
(Макрозадачи: включитьsetTimeout
а такжеsetInterval
и т.д.) иmicro task
(Микрозадачи: включитьnew Promise
д.), вJavaScript
В стеке выполнения, если одновременно есть макрозадачи и микрозадачи с истекшим сроком действия, сначала будут выполняться все микрозадачи, а затем будет выполняться первая макрозадача Таким образом, в двух асинхронных операцияхthen
Обратный вызов будет выполнен первым, затемsetTimeout
Обратный вызов, поэтому он будет выводить 3, 1 по очереди, поэтому окончательный результат вывода будет 2, 3, 1.
6. ES6 Сфера действия и разница между пусть и var
Учитель в учителеНачало работы с ECMAScript 6серединаlet 和 const 命令
В этой главе дается подробное описание этого вопроса, а ниже извлекаются некоторые из ключевых моментов, которые, как мне кажется, объясняются.
ES6 представил использование{}
Обернутая область кода используется как метод объявления блочной области видимости, и ее действие такое же, как и в ES5.function
Область действия функции, сгенерированная объявленной функцией, имеет тот же эффект. Функции или переменные, объявленные внутри области, не могут быть доступны за ее пределами. Такие объявления используются в ES6 для включенияfor () {}
,if () {}
Это вступит в силу в блоках кода, заключенных в фигурные скобки, что приведет к отдельной области действия.
Новое в ES6let
По сравнению с тем, как вы объявляете переменныеvar
Имеет следующие важные особенности:
-
let
Объявленная переменная действительна только в пределах области действия, как показано в следующем коде:if
Объявление создает область на уровне блока, и переменные, объявленные в этой области, не могут быть доступны за пределами области, и при доступе произойдет ошибка:
if (true) {
let me = 'handsome boy';
}
console.log(me); // ReferenceError
-
let
объявленная переменная сvar
Другое дело, никакого подъема переменной не произойдет.Следующий код, выводящий код перед объявлением, выдаст ошибку:
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // ReferenceError
let bar = 2;
-
let
Метод объявления не допускает повторных объявлений, таких как повторные объявления, будет сообщено об ошибке, иvar
При объявлении переменной оператор, объявленный позже, переопределяет оператор, объявленный ранее:
// 报错
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
- Пока существует область действия блока
let
команда, переменные, которые она объявляет, являются "связанными" (binding
) эту область, уже не подверженную внешним воздействиям, эта особенность называется暂时性死区
.
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
7. Закрытие
Быть добавленным
8. Прототип и цепочка прототипов
Быть добавленным
9. Reflow & Repaint браузера
Ссылаться на:nuggets.capable/post/684490…
Браузер получаетhtml
а такжеcss
После этого этапы рендеринга следующие:html
Создано путем рендерингаDOM
Дерево,css
Создано путем рендерингаcss
Дерево рендеринга, они объединяются для созданияrender tree
, браузер можетrender tree
Выполнение экранного рисунка.
Если браузер получает новыйcss
, что нужно сделать, когда страницу нужно обновить? это обратный потокreflow
с перекраскойrepaint
. Поскольку браузер сначала повторно отображает страницуreflow
сделай это сноваrepaint
, поэтому перекомпоновка обязательно вызовет перерисовку, а перерисовка не обязательно приведет к перекомпоновке.
Перерисовка: при изменении стиля текущего элемента (цвет фона, цвет шрифта и т. д.) нам нужно только повторно отобразить измененный элемент, и перерисовка мало влияет на производительность браузера. При перерисовке: изменить стиль внешнего вида контейнера и т. д., напримерbackground:black
Ждать. Измените внешний вид, не меняйте раскладку, не влияйте на другиеDOM
.
Reflow: относится к процессу, с помощью которого браузер пересчитывает положение и геометрию элементов в документе, чтобы повторно отобразить часть или весь документ.
Поскольку обратный поток может привести кDOM
Реструктуризация дерева, так что это большой убийца производительности, перекомпоновка элемента вызывает все его дочерние элементы иDOM
Последующие перекомпоновки непосредственно следующего за ним элемента-предка в . Опубликовано ниже вызовет браузерreflow
Изменение:
- первый рендер страницы
- Изменился размер окна браузера
- Изменение размера или положения элемента
- Изменения содержимого элемента (количество текста или размер изображения и т. д.)
- Изменение размера шрифта элемента
- Добавить или удалить видимые элементы DOM
- Активировать псевдоклассы CSS (например: :hover )
- запрашивать определенные свойства или вызывать определенные методы
Оптимизация:
CSS
- избегать использования
table
макет. - как можно больше
DOM
Конец дерева измененийclass
. - Избегайте установки нескольких слоев встроенных стилей.
- Применение анимационных эффектов к
position
собственностьabsolute
илиfixed
на элементе. - избегать использования
CSS
выражения (например:calc()
).
JavaScript
- Избегайте частых манипуляций со стилями, лучше всего переписать их все сразу
style
или определите список стилей какclass
и поменять все сразуclass
Атрибуты. - Избегайте частых операций
DOM
,СоздаватьdocumentFragment
, на него распространяются всеDOM
операцию и, наконец, добавьте ее в документ. - Вы также можете сначала установить элемент
display: none
, и отображать его после завершения операции. Потому чтоdisplay
собственностьnone
выполняется на элементахDOM
Операции не вызывают перекомпоновки и перерисовки. - Избегайте частого чтения свойств, которые вызовут перекомпоновку/перерисовку, и если вам действительно нужно использовать их несколько раз, кэшируйте их в переменной.
- Используйте абсолютное позиционирование для элементов со сложной анимацией, чтобы они не попадали в поток документа, иначе это вызовет частые перекомпоновки родительских и последующих элементов.
10. Глубокое копирование объектов JS
Общая идея состоит в том, чтобы решить ее рекурсивно и выполнить различную обработку для разных типов данных:
function deepCopy (obj) {
let result = {}
for (let key in obj) {
if (obj[key] instanceof Object || obj[key] instanceof Array) {
result[key] = deepCopy(obj[key])
} else {
result[key] = obj[key]
}
}
return result
}
Это может только копировать объекты с массивами, объектами или другими базовыми типами данных внутри, если есть такие объекты, какRegExp
,Date
Результатом такой сложной копии объекта является{}
, не могут быть правильно скопированы, потому что для этих специальных объектов не предусмотрена отдельная обработка. Чтобы обратиться к копированию сложных объектов, вы можете обратиться кlodash
Метод глубокого копирования среднего массива_.cloneDeep()
В следующей статье представлен подробный анализ метода глубокого копирования массивов, который имеет определенное справочное значение:Джерри go.com/posts/dive-…
Кроме того, если структура данных копируемого объекта относительно проста и отсутствуют данные сложных объектов, то можно использовать самый простой способ:
let cloneResult = JSON.parse(JSON.stringify(targetObj))
11. Теряется точность работы JS
Ранее я перепечатывал статью, в которой есть более подробное описание причин и решений потери точности работы JavaScript:blog.CSDN.net/QQ_35271556…
Связанные с браузером
1. Процесс браузера от загрузки до рендеринга, например, процесс ввода URL-адреса для отображения страницы.
Процесс загрузки:
- Браузер получает IP-адрес доменного имени в соответствии с разрешением DNS-сервера.
- Отправьте HTTP-запрос на машину с этим IP-адресом
- Сервер получает, обрабатывает и возвращает HTTP-запрос
- Браузер получает возвращаемый контент
Процесс рендеринга:
- Сгенерировать дерево DOM из структуры HTML
- Создание CSSOM из CSS
- Интегрируйте DOM и CSSOM для формирования RenderTree
- Начать рендеринг и отображение в соответствии с RenderTree
- встретить
<script>
, выполнит и заблокирует рендеринг
2. Механизм кэширования браузера
Справочная статья:сегмент fault.com/ah/119000001…
3. Оптимизация производительности
Справочная статья:blog.CSDN.net/that_sama/art…
Vue
1. Связь между компонентами
Официальная документация Vue содержит подробное описание метода связи между компонентами:cn.vuejs.org
родительский компонент в дочерний компонент
- Самый распространенный способ — передать данные в теге подкомпонента и использовать их внутри подкомпонента.
props
перенимать:
// 父组件
<template>
<children name="boy"></children>
</template>
<script>
// 子组件:children
export default {
props: {
name: String
}
}
</script>
- также может использоваться в подкомпонентах
this.$parent
Доступ к экземпляру родительского компонента, но в официальном документе есть такой абзац, что является хорошим объяснением$parent
Значение: использовать экономно$parent
а также$children
- Их основная цель - обходной путь для доступа к компонентам. больше рекомендуетсяprops
а такжеevents
Реализовать связь между родительскими и дочерними компонентами.
дочерний компонент к родительскому компоненту
- Обычно используется в подкомпонентах
this.$emit('eventName', 'data')
, а затем прослушайте тег дочернего компонента в родительском компонентеeventName
событие и получить переданное значение в параметре.
// 子组件
export default {
mounted () {
this.$emit('mounted', 'Children is mounted.')
}
}
<template>
<children @mounted="mountedHandle"></children>
</template>
<script>
// 父组件
export default {
methods: {
mountedHandle (data) {
console.log(data) // Children is mounted.
}
}
}
</script>
- а также
$parent
Например, в родительском компоненте можно получить доступ кthis.$children
для доступа ко всем экземплярам дочерних компонентов компонента.
Передача данных между неродительскими и дочерними компонентами
-
Для компонентов, не являющихся родительскими и дочерними, со сложной иерархией компонентов вы можете использовать
Vuex
Передача данных между компонентами:vuex.vuejs.org/zh/ -
существует
Vue 1.0
обычно используется вevent bus
глобальная передача данных с помощьюVue 2.0
был удален в официальной документации, как указано в официальной документации:$dispatch
а также$broadcast
устарело. Пожалуйста, используйте более лаконичную и четкую межкомпонентную коммуникацию и лучшие схемы управления состоянием, такие как:Vuex
.
2, двусторонний принцип привязки
blog.seosiwei.com/detail/35 blog.seosiwei.com/detail/36 blog.seosiwei.com/detail/37
3, навигационный крючок маршрутизации
router.v ue js.org/this-capable/advpress…