Кисть «Полтора года опыта, резюме интервью Baidu, Youzan, Ali» · Заметки

Байду JavaScript CSS опрос

На «Наггетс» я увидел крупного парня, опубликовавшего очень подробную статью с записью интервью:«Полтора года опыта, резюме интервью 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: снова поговорим о цикле событий»Сказано очень четко (ручная похвала)!

Ниже следует краткое изложение:

  1. JS однопоточный, все его задачи выполняются в двух местах:Стек выполнения и очередь задач. Первый предназначен для хранения синхронных задач, второй — для помещения события в асинхронную задачу после получения результата.
  2. Когда все задачи в стеке выполнения выполнены (стек пуст), js прочитает очередь задач и бросит задачи, которые могут быть выполнены, из очереди задач в стек выполнения для выполнения.
  3. Этот процесс цикличен, поэтому его называют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изflexlayout, для атрибута отображения родительского элемента установлено значение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-адрес, чтобы увидеть весь процесс страницы, чем подробнее, тем лучше

  1. разрешение DNS
  2. Установить TCP-соединение (3-стороннее рукопожатие)
  3. Отправьте HTTP-запрос для загрузки соответствующего контента с сервера.
  4. Браузер строит дерево DOM и дерево CSS, а затем генерирует дерево рендеринга. Это постепенный процесс, и движок будет стремиться представить контент пользователю как можно быстрее.
  5. Во время четвертого шага<script>Расположение и способ загрузки будут влиять на скорость отклика.
  6. Готово, закрыть 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 ]. . . . Какова временная сложность вашего алгоритма

Идея реализации: из «начального элемента» каждый элемент заменяется начальным элементом; область действия постоянно сужается, и, наконец, это расположение выводится. Временная сложность закона грубой силы равнаO(N_N), временная сложность рекурсивной реализации равнаO(N!)

**Как убрать вес? Полная перестановка дедупликации заключается в замене каждого числа из первого числа неповторяющимся числом после него. **Для массивов с повторяющимися элементами, например:[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» · Заметки