На «Наггетс» я увидел крупного парня, опубликовавшего очень подробную статью с записью интервью:«Полтора года опыта, резюме интервью Baidu, Youzan, Ali», Для того, чтобы проверить герметичность и заполнить пробелы, я нашел время сделать это подробно. (Наверное, я единственный, кто такой скучный, ха-ха)
Ответы даны или неполные, и я постарался их дать/усовершенствовать (могут быть ошибки, каждый сам их определит). некоторые очень сложные проблемы (например, реализацияPromise
) с соответствующими ссылками (пособия для ленивых больных раком).
В целом эти вопросы разделены на 5 частей: «Javascript», «CSS», «Браузер/Протокол», «Алгоритм» и «Веб-инженерия» для ответов и реализации кода.
Наконец, добро пожаловать в мой блог, чтобы пообщаться со мной:godbmw.com. Непосредственно штамповать адрес оригинального текста этой статьи:Кисть «Полтора года опыта, резюме интервью Baidu, Youzan, Ali» · Заметки
1. Связанный с Javascript
1.1 Палиндромные строки
Тема: Реализуйте функцию для определения того, является ли строка палиндромом
Первоначальная идея состоит в том, чтобы преобразовать строку в массив => перевернуть массив => объединить в строку.Этот подход полностью использует BIF js, но производительность ухудшается.:
function run(input) {
if (typeof input !== 'string') return false;
return input.split('').reverse().join('') === input;
}
На самом деле нормального мышления добиться очень просто,Более высокая производительность, но не используются возможности js:
// 回文字符串
const palindrome = (str) => {
// 类型判断
if(typeof str !== 'string') {
return false;
}
let len = str.length;
for(let i = 0; i < len / 2; ++i){
if(str[i] !== str[len - i - 1]){
return false;
}
}
return true;
}
1.2 РеализацияStorage
Тема: Реализовать Storage, сделать объект синглтоном и инкапсулировать localStorage для установки значений setItem(key, value) и getItem(key)
В центре внимания темыодноэлементный шаблон, следует отметить, что сlocalStorage
, вместо того, чтобы позволять себе делать это вручную!
благодарный@whiteyork_а также@chenzesamНапоминание: функции со стрелками неprototype
function Storage(){}
Storage.getInstance = (function(){
var instance = null
return function(){
if(!instance){
instance = new Storage()
}
return instance
}
})()
Storage.prototype.setItem = function(key, value) {
return localStorage.setItem(key, value)
}
Storage.prototype.getItem = function(key){
return localStorage.getItem(key)
}
// 测试代码:Chrome环境
let a = Storage.getInstance()
let b = Storage.getInstance()
console.log(a === b)
a.setItem("key", 1)
console.log(b.getItem("key"))
1.3 Поток событий JS
Тема: Поговорим о потоке событий
Поток событий делится на всплытие и захват.
Всплывание событий: триггерное событие дочернего элемента будет передаваться родительскому узлу до тех пор, пока корневой узел не остановится. В ходе этого процесса соответствующие события могут быть зафиксированы на каждом узле. в состоянии пройтиstopPropagation
способ перестать пузыриться.
Захват событий: в отличие от «пузырькового распространения событий», выполнение начинается с корневого узла и продолжается на дочерних узлах до целевого узла. ~~ У меня сложилось впечатление, что только несколько старых версий браузеров имеют такой поток событий и могут быть проигнорированы. ~~ В том, что я сказал здесь, действительно есть проблема, пожалуйста, исправьте это:addEventLister
Третий параметр задается для поддержки всплытия и захвата.
благодарный@junior-yangнапоминание
1.4 Реализация функционального наследования
Вопрос: Теперь есть функция A и функция B, пожалуйста, реализуйте B, чтобы наследовать A. и объяснить их преимущества и недостатки.
Способ 1: привязать конструктор
Преимущество: может быть достигнуто множественное наследование
Недостаток: нельзя наследовать методы/свойства прототипа родительского класса.
function Animal(){
this.species = "动物";
}
function Cat(){
Animal.apply(this, arguments); // 父对象的构造函数绑定到子节点上
}
var cat = new Cat()
console.log(cat.species) // 输出:动物
Метод 2: наследование цепочки прототипов
Преимущества: возможность наследовать прототипы родительского класса и методы/свойства экземпляра, а также фиксировать изменения цепочки прототипов родительского класса.
Недостатки: Множественное наследование невозможно, и часть памяти будет потрачена впустую (Cat.prototype.constructor = Cat
).Кроме того, следует отметить, чтоCat.prototype.constructor
Переточка себя.
Цепочка прототипов обмена в js, все нужно чинитьprototype.constructor
указать на проблему.
function Animal(){
this.species = "动物";
}
Animal.prototype.func = function(){
console.log("heel")
}
function Cat(){}
Cat.prototype = new Animal()
Cat.prototype.constructor = Cat
var cat = new Cat()
console.log(cat.func, cat.species)
Способ 3: Объедините два вышеуказанных метода.
function Animal(){
this.species = "动物";
}
Animal.prototype.func = function(){
console.log("heel")
}
function Cat(){
Animal.apply(this, arguments)
}
Cat.prototype = new Animal()
Cat.prototype.constructor = Cat;
var cat = new Cat()
console.log(cat.func, cat.species)
1.5 Объекты ES5 и объекты ES6
Тема: В чем разница между новым экземпляром класса es6 и новым экземпляром es5?
существуетES6
нейтрализоватьES5
в сравнении с),class
изnew
Экземпляры имеют следующие характеристики:
-
class
Параметр конструктора должен бытьnew
чтобы вызвать его, он не может быть выполнен как обычная функция -
es6
изclass
Нет переменного продвижения -
самое главное это:
es6
Внутренние методы не перечислимы. es5prototype
Методы можно перечислить.
Для этого я сделал следующий тестовый код для проверки:
console.log(ES5Class()) // es5:可以直接作为函数运行
// console.log(new ES6Class()) // 会报错:不存在变量提升
function ES5Class(){
console.log("hello")
}
ES5Class.prototype.func = function(){ console.log("Hello world") }
class ES6Class{
constructor(){}
func(){
console.log("Hello world")
}
}
let es5 = new ES5Class()
let es6 = new ES6Class()
console.log("ES5 :")
for(let _ in es5){
console.log(_)
}
// es6:不可枚举
console.log("ES6 :")
for(let _ in es6){
console.log(_)
}
это"JavaScript создание объектов - от es5 до es6"Хорошее подробное объяснение темы, рекомендуем к просмотру!
1.6 РеализацияMVVM
Тема: Пожалуйста, просто реализуйте двустороннюю привязку данных mvvm
**vuejs используетObject.defineProperty
Для реализации MVVM используется модель публикации по подписке. **Каждыйdata
Есть атрибуты set и get вAngular
Способ реализации MVVM более эффективен.
<body>
<input type="text">
<script>
const input = document.querySelector('input')
const obj = {}
Object.defineProperty(obj, 'data', {
enumerable: false, // 不可枚举
configurable: false, // 不可删除
set(value){
input.value = value
_value = value
// console.log(input.value)
},
get(){
return _value
}
})
obj.data = '123'
input.onchange = e => {
obj.data = e.target.value
}
</script>
</body>
1.7 РеализацияPromise
Это делает большой пареньPromise
Версия:проходитьPromie/A+
стандартный тест! ! !В основном все, что можно найти в Интернете, искажено из этой статьи или скопировано напрямую.! ! ! Оригинальный адрес, прямая печать:Проанализируйте внутреннюю структуру Promise, шаг за шагом, чтобы реализовать полный класс Promise, который может пройти все тестовые случаи.
Почти идеальная реализация прилагается ниже: может не работать с другимиPromise
Реализация библиотеки бесшовная. Тем не менее, приведенный выше исходный текст достигает всего, добро пожаловать, Марк!
function MyPromise(executor){
var that = this
this.status = 'pending' // 当前状态
this.data = undefined
this.onResolvedCallback = [] // Promise resolve时的回调函数集,因为在Promise结束之前有可能有多个回调添加到它上面
this.onRejectedCallback = [] // Promise reject时的回调函数集,因为在Promise结束之前有可能有多个回调添加到它上面
// 更改状态 => 绑定数据 => 执行回调函数集
function resolve(value){
if(that.status === 'pending'){
that.status = 'resolved'
that.data = value
for(var i = 0; i < that.onResolvedCallback.length; ++i){
that.onResolvedCallback[i](value)
}
}
}
function reject(reason){
if(that.status === 'pending'){
that.status = 'rejected'
that.data = reason
for(var i = 0; i < that.onResolvedCallback.length; ++i){
that.onRejectedCallback[i](reason)
}
}
}
try{
executor(resolve, reject) // resolve, reject两个函数可以在外部传入的函数(executor)中调用
} catch(e) { // 考虑到执行过程可能有错
reject(e)
}
}
// 标准是没有catch方法的,实现了then,就实现了catch
// then/catch 均要返回一个新的Promise实例
MyPromise.prototype.then = function(onResolved, onRejected){
var that = this
var promise2
// 值穿透
onResolved = typeof onResolved === 'function' ? onResolved : function(v){ return v }
onRejected = typeof onRejected === 'function' ? onRejected : function(r){ return r }
if(that.status === 'resolved'){
return promise2 = new MyPromise(function(resolve, reject){
try{
var x = onResolved(that.data)
if(x instanceof MyPromise){ // 如果onResolved的返回值是一个Promise对象,直接取它的结果做为promise2的结果
x.then(resolve, reject)
}
resolve(x) // 否则,以它的返回值做为promise2的结果
} catch(e) {
reject(e) // 如果出错,以捕获到的错误做为promise2的结果
}
})
}
if(that.status === 'rejected'){
return promise2 = new MyPromise(function(resolve, reject){
try{
var x = onRejected(that.data)
if(x instanceof MyPromise){
x.then(resolve, reject)
}
} catch(e) {
reject(e)
}
})
}
if(that.status === 'pending'){
return promise2 = new MyPromise(function(resolve, reject){
self.onResolvedCallback.push(function(reason){
try{
var x = onResolved(that.data)
if(x instanceof MyPromise){
x.then(resolve, reject)
}
} catch(e) {
reject(e)
}
})
self.onRejectedCallback.push(function(value){
try{
var x = onRejected(that.data)
if(x instanceof MyPromise){
x.then(resolve, reject)
}
} catch(e) {
reject(e)
}
})
})
}
}
MyPromise.prototype.catch = function(onRejected){
return this.then(null, onRejected)
}
// 以下是简单的测试样例:
new MyPromise(resolve => resolve(8)).then(value => {
console.log(value)
})
1.8 Event Loop
Тема: Разговор о EventLoop в JS
На самом деле учитель Жуань Ифэн«Подробное объяснение механизма выполнения JavaScript: снова поговорим о цикле событий»Сказано очень четко (ручная похвала)!
Ниже следует краткое изложение:
- JS однопоточный, все его задачи выполняются в двух местах:Стек выполнения и очередь задач. Первый предназначен для хранения синхронных задач, второй — для помещения события в асинхронную задачу после получения результата.
- Когда все задачи в стеке выполнения выполнены (стек пуст), js прочитает очередь задач и бросит задачи, которые могут быть выполнены, из очереди задач в стек выполнения для выполнения.
- Этот процесс цикличен, поэтому его называют
Loop
.
2. Связанный с CSS
2.1 Горизонтальное и вертикальное центрирование
Вопрос: Два или более способов добиться вертикального и горизонтального центрирования известной или неизвестной ширины
Первый метод заключается в использованииCSS3
изtranslate
Смещение позиционирования,Примечание. Проценты для обоих параметров рассчитываются для самого элемента.
.wrap {
position: relative;
width: 100vw;
height: 100vh;
}
.box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Второй метод заключается в использованииCSS3
изflex
layout, для атрибута отображения родительского элемента установлено значениеflex
, и определите, что расположение элементов по обеим осямcenter
.wrap {
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
.wrap .box {
width: 100px;
height: 100px;
}
Третий метод заключается в использованииотрицательная маржаДля выполнения смещения элемента преимущество в том, что браузер совместим, но недостаток в том, что он недостаточно гибок (значение отступа нужно вычислять самому):
.wrap {
position: relative;
width: 100vw;
height: 100vh;
}
.box {
position: absolute;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
margin: -50px 0 0 -50px;
}
2.2 "Нажмите", чтобы изменить стиль
Тема: Для достижения эффекта щелкните значок в контейнере, граница значка станет сплошной красной рамкой толщиной 1 пиксель, щелкните пустое место для сброса.
использоватьevent.target
Вы можете судить о том, является ли он указанным элементом по себе (судя по «пустому месту»), кроме того, обратите внимание на запрет всплытия (в заголовке указано «в контейнере»).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#app {
min-width: 100vw;
min-height: 100vh;
}
#app .icon{
display: inline-block;
cursor: pointer;
}
</style>
</head>
<body>
<div id="app">
<span class="icon">123456</span>
</div>
<script>
const app = document.querySelector("#app")
const icon = document.querySelector(".icon")
app.addEventListener("click", e => {
if(e.target === icon){
return;
}
// 非空白处才去除 border
icon.style.border = "none";
})
icon.addEventListener("click", e => {
// 禁止冒泡
e.stopPropagation()
// 更改样式
icon.style.border = "1px solid red";
})
</script>
</body>
</html>
3. Браузер/протокол
3.1 Механизм кэширования
Тема: Расскажите о механизме кеширования браузера.
кеш браузераКэш-кэш делится на крепкий и консультационный. Роль кэшаУлучшите скорость клиента, сэкономьте сетевой трафик, уменьшите нагрузку на сервер.
Сильный кеш: браузер запрашивает ресурсы, если заголовокCache-Control
а такжеExpires
Нет истечения срока действия, а ресурсы считываются напрямую из кеша (локального), и нет необходимости запрашивать ресурсы с сервера.
Кэш согласования: браузер запрашивает ресурс, если он просрочен, затем отправляет запрос на сервер, заголовок сEtag
поле. Сервер делает другое суждение.Если ETag совпадает, он возвращает клиенту код состояния серии 300, и клиент продолжает использовать локальный кеш, в противном случае клиент повторно получит ресурс данных.
Для получения подробных полей в процессе вы можете обратиться к этому "Кэш согласования http против сильного кеша》
3.2 От URL к генерации страницы
Тема: введите URL-адрес, чтобы увидеть весь процесс страницы, чем подробнее, тем лучше
- разрешение DNS
- Установить TCP-соединение (3-стороннее рукопожатие)
- Отправьте HTTP-запрос для загрузки соответствующего контента с сервера.
- Браузер строит дерево DOM и дерево CSS, а затем генерирует дерево рендеринга. Это постепенный процесс, и движок будет стремиться представить контент пользователю как можно быстрее.
- Во время четвертого шага
<script>
Расположение и способ загрузки будут влиять на скорость отклика. - Готово, закрыть TCP-соединение (4-стороннее рукопожатие)
3.3 TCP-рукопожатие
Тема: Объясните трехэтапное рукопожатие при установленном TCP и четырехэтапное рукопожатие при его закрытии.
Когда я прочитал этот вопрос, я тоже внезапно обомлел (закрыв лицо руками). Рекомендуется читать книги, связанные с компьютерной сетью, дляFIN
,ACK
Объяснение полей отличное!
3.4 Расположение CSS и JS
Тема: Позиция CSS и JS повлияет на эффективность страницы и почему?
Начнем с CSS. Расположение CSS не влияет на скорость загрузки, но CSS обычно размещается в<head>
в этикетке. Как упоминалось ранее, дерево DOM и дерево CSS совместно создают дерево рендеринга.Если положение CSS слишком далеко назад, до загрузки CSS могут возникнуть такие ситуации, как заставка, путаница стилей и белый экран.
Скажи JS еще раз. JS блокирует загрузку, по умолчанию<script>
Тег сразу загрузит и выполнит скрипт, если скрипт сложный или сеть плохая, будет длинный белый экран. Поэтому теги JS обычно размещаются в<body>
Этикетка последняя.
Теперь также можно<script>
Настройки ярлыкаasync
илиdefer
Атрибуты. Первый заключается в том, что загрузка и выполнение js-скриптов будет выполняться синхронно с загрузкой и рендерингом последующих документов. Последнее заключается в том, что загрузка js-скрипта будет выполняться синхронно с загрузкой и рендерингом последующих документов, когда все элементы будут разобраны, js-скрипт будет выполнен.
4. Связанный с алгоритмом
4.1 Полное расположение массива
Вопрос: Теперь есть массив [1,2,3,4], пожалуйста, реализуйте алгоритм, чтобы получить полный массив этого массива, например [2,1,3,4], [2,1,4,3 ]. . . . Какова временная сложность вашего алгоритма
Идея реализации: из «начального элемента» каждый элемент заменяется начальным элементом; область действия постоянно сужается, и, наконец, это расположение выводится. Временная сложность закона грубой силы равна, временная сложность рекурсивной реализации равна
**Как убрать вес? Полная перестановка дедупликации заключается в замене каждого числа из первого числа неповторяющимся числом после него. **Для массивов с повторяющимися элементами, например:[1, 2, 2]
, дубликаты должны быть устранены. Просто проверяйте каждый разarr[start, i)
Есть ли гармония вarr[i]
Те же элементы, если они есть, были выведены ранее и не нуждаются в рассмотрении.
Код:
const swap = (arr, i, j) => {
let tmp = arr[i]
arr[i] = arr[j]
arr[j] = tmp
}
const permutation = arr => {
const _permutation = (arr, start) => {
if(start === arr.length){
console.log(arr)
return
}
for(let i = start; i < arr.length; ++i){
// 全排列:去重操作
if(arr.slice(start, i).indexOf(arr[i]) !== -1){
continue
}
swap(arr, i, start) // 和开始元素进行交换
_permutation(arr, start + 1)
swap(arr, i, start) // 恢复数组
}
return
}
return _permutation(arr, 0)
}
permutation([1, 2, 2])
console.log("**********")
permutation([1, 2, 3, 4])
4.2 Проблема рюкзака
Вопрос: Теперь у меня есть рюкзак вместимостью m, а затем есть n предметов с весами w1, w2, w3...wn, и стоимость каждого предмета равна v1, v2, v3...vn, w и v Неважно, запросите максимальное значение, которое может вместить рюкзак.
Это еще учеба, проблема ранца обширна и глубока. . .
4.3 Связные компоненты графа
Вопрос: Теперь у меня есть холст с несколькими черными блоками, случайно распределенными по нему. Пожалуйста, реализуйте метод для подсчета количества черных блоков на холсте.
Эта задача может быть преобразована в задачу о связных компонентах графа.. пройти черезgetImageData
Получите массив пикселей и пройдите его от начала до конца, чтобы определить, является ли каждый пиксель черным. Тем временем подготовьтеwidth * height
Двумерный массив размера, каждый элемент этого массива1/0
. Если вы черный, двумерный массив соответствует элементу набора 1; 0 в противном случае.
Затем задача преобразуется в задачу компонент связности графа. Это может быть достигнуто с помощью обхода в глубину или поиска по объединению. Я уже реализовал это на C++, поэтому не буду повторяться здесь:
5. Веб-инженерия
5.1 Идея диалогового компонента
Тема: Теперь я хочу, чтобы вы завершили компонент «Диалог», расскажите о своих дизайнерских идеях? Какую функцию он должен иметь?
- Требуется наложение для покрытия основного содержимого
- Состоит из головы, хвоста и тела
- Необходимо отслеживать события и пользовательские события, неоднонаправленный поток данных: например, щелкните в правом верхнем углу компонента, чтобы изменить родительский компонент.
visible
свойство, чтобы закрыть компонент.
Для инкапсуляции инженерных компонентов вы можете попробовать ElementUI. Это диалоговый компонент ElementUI:Element-Dialog
5.2 Алгоритм сравнения React и виртуальный DOM
Тема: Как реализован виртуальный дом реакции?
Оригинальный ответ очень хорошо написан, поэтому я вставлю его прямо сюда.
首先说说为什么要使用Virturl DOM,因为操作真实DOM的耗费的性能代价太高,所以react内部使用js实现了一套dom结构。
在每次操作在和真实dom之前,使用实现好的diff算法,对虚拟dom进行比较,递归找出有变化的dom节点,然后对其进行更新操作。
为了实现虚拟DOM,我们需要把每一种节点类型抽象成对象,每一种节点类型有自己的属性,也就是prop,每次进行diff的时候,react会先比较该节点类型:
假如节点类型不一样,那么react会直接删除该节点,然后直接创建新的节点插入到其中;
假如节点类型一样,那么会比较prop是否有更新,假如有prop不一样,那么react会判定该节点有更新,那么重渲染该节点,然后在对其子节点进行比较,一层一层往下,直到没有子节点。
Ссылка на ссылку:Алгоритм сравнения исходного кода React
Наконец, добро пожаловать в мой блог, чтобы пообщаться со мной:godbmw.com. Непосредственно штамповать адрес оригинального текста этой статьи:Кисть «Полтора года опыта, резюме интервью Baidu, Youzan, Ali» · Заметки