Вопросы, которые мне задавали на фронтенд-собеседованиях

от автора

Всем привет. В сентябре OTUS вновь запускает целую линейку курсов по JavaScript. Прямо сейчас вы можете посмотреть запись открытого урока по курсу «JavaScript Developer. Professional», а также зарегистрироваться на дни открытых дверей по курсам «React.js Developer» и «JavaScript Developer. Basic». Ну а мы традиционно делимся с вами переводом полезного материала.


Фронтенд-собеседование (в 2 частях)

1. Вопросы, которые мне задавали на фронтенд-собеседованиях.

2. Ресурсы для подготовки к собеседованию (на должность фронтенд-разработчика).

Вопросы, которые задавали на фронтенд-собеседованиях


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

Вопросы я разделил на четыре части.

  • JS

  • Код

  • Задачи

  • Другие вопросы

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

Отредактировано 20.08.2020. Посмотреть изменения

JS

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

Решение:

/**  * [1,2,[3,4]] -> [1,2,3,4]  */  let arr = [1,2,[3,4, [5,6, [7, [8, 9, 10]]]]]  function flatten(arr) {   return arr.reduce(function(acc, next){     let isArray =  Array.isArray(next)     return acc.concat(isArray ? flatten(next) : next)   }, []) }  if (!Array.prototype.flatten) {   Array.prototype.flatten = function() {     return flatten(this)   } } console.log(arr.flatten()); 

2. Создайте промис с нуля

Решение:

class CustomPromise {   state = "PENDING"   value = undefined   thenCallbacks = []   errorCallbacks = []    constructor(action) {     action(this.resolver.bind(this), this.reject.bind(this))   }    resolver(value) {     this.state = "RESOLVED"     this.value = value     this.thenCallbacks.forEach((callback) => {       callback(this.value)     })   }    reject(value) {     this.state = "REJECTED"     this.value = value     this.errorCallbacks.forEach((callback) => {       callback(this.value)     })   }    then(callback) {     this.thenCallbacks.push(callback)     return this    }    catch (callback) {     this.errorCallbacks.push(callback)     return this    } }  let promise = new CustomPromise((resolver, reject) => {   setTimeout(() => {     const rand = Math.ceil(Math.random(1 * 1 + 6) * 6)     if (rand > 2) {       resolver("Success")     } else {       reject("Error")     }   }, 1000) })  promise   .then(function(response){     console.log(response)   })   .catch(function(error){     console.log(error)   }) 

3. Отфильтруйте список фильмов по среднему рейтингу, названию. Отсортируйте отфильтрованный список по любому полю.

Решение:

// O(M) function getMovies() {   return []; // [{id, name, year}] }  // O(R) function getRatings() {   return []; // [{id, movie_id, rating}]   0 <= rating <= 10   // e.g 9.3 }  /**  * minAvgRating ->  *    avgRating >= minAvgRating  *  * sort ->  *    name -> ascending order movies by name  *   -name -> descending  *  *    avgRating  *   *  * search ->  *   'ave' -> 'Avengers'  *   'avengers' -> 'Avengers'  *   'AvengersInfinitywar' -> 'Avengers'  */ const toLower = str => str.toLocaleLowerCase()  const getAvrgRating = (movie, movingWithRatings) => {   let count = 0;   return movingWithRatings.reduce((acc, value, index) => {     const movieMatch = movie.id === value.movie_id     if (movieMatch) {       acc+=value.rating       count++     }     if (index === movingWithRatings.length - 1) {       acc = acc/count     }     return acc   }, 0) }  const isSubString = (str1, str2) => {   str1 = toLower(str1.split(" ").join(""))   str2 = toLower(str2.split(" ").join(""))   if (str1.length > str2.length) {     return str1.startWith(str2)   } else {     return str2.startWith(str1)   } }  const moviesList = getMovies() const movingWithRatings = getRatings(); function queryMovies({ search, sort, minAvgRating }) {   let filteredMovies = movingWithRatings.filter(movie => getAvrgRating(movie, movingWithRatings) >= minAvgRating);   filteredMovies = filteredMovies.map(movie => moviesList.filter(listItem => listItem.id === movie.movie_id).pop())   filteredMovies = filteredMovies.filter(movie => isSubString(toLower(movie.name), toLower(search)))   filteredMovies = filteredMovies.sort((a, b) => {     const isDescending = sort[0] === '-' ? true : false     let sortCopy = isDescending ? sort.slice(1) : sort     const value1 = a[sortCopy]     const value2 = b[sortCopy]     if (isDescending) {       return value1 > value2 ? -1 : 1     }else {       return value1 < value2 ? -1 : 1     }   })   filteredMovies = filteredMovies.map(movie => ({     ...movie,     avgRating: movingWithRatings.filter(ratedMovie => ratedMovie.movie_id === movie.id)[0].rating   }))   return filteredMovies } 

4. Загрузите все публикации и комментарии по URL-адресу конечной точки. Выполните следующее.

  • Соотнесите все комментарии с публикациями, к которым они относятся. В результате данные должны иметь следующую структуру.

Решение:

//service.js const POSTS_URL = `https://jsonplaceholder.typicode.com/posts`; const COMMENTS_URL = `https://jsonplaceholder.typicode.com/comments`;  export const fetchAllPosts = () => {   return fetch(POSTS_URL).then(res => res.json()); };  export const fetchAllComments = () => {   return fetch(COMMENTS_URL).then(res => res.json()); };   import { fetchAllPosts, fetchAllComments } from "./service";    const fetchData = async () => {   const [posts, comments] = await Promise.all([     fetchAllPosts(),     fetchAllComments()   ]);    const grabAllCommentsForPost = postId =>     comments.filter(comment => comment.postId === postId);    const mappedPostWithComment = posts.reduce((acc, post) => {     const allComments = grabAllCommentsForPost(post.id);     acc[post.id] = allComments;     return acc;   }, {});    console.log("mappedPostWithComment ", mappedPostWithComment); };  fetchData(); 

5. Реализуйте метод getHashCode в экземпляре объекта string. Метод должен быть доступен для всех строк.

Решение:

let s1 = "sample"  if (!String.prototype.getHashCode) {   String.prototype.getHashCode = function(){     console.log('String instance ', this)     return this   } } 

6. Какой результат будет у приведенных ниже выражений?

    1+true     true+true     ‘1’+true     ‘2’ > ’3’     ‘two’>’three’ 

Решение:

2 2 1true false true

7. Реализуйте методы bind и reduce.

Решение:

//bind if (!Function.prototype.bind) {   Function.prototype.bind = function(...arg){     const func = this     const context = arg[0]     const params = arg.slice(1)     return function(...innerParam) {       func.apply(context, [...params, ...innerParam])     }   } }  //reduce Array.prototype.reduce = function(func, initState) {   const arr = this   const callback = func   let init = initState    arr.forEach(function(value, index){       init=callback(init, value)   })   return init } 

8. Реализуйте функцию debounce

Решение:

const debounce = function(func, interval) {   let timerId;   return function(e){     clearTimeout(timerId)     timerId = setTimeout(function(){       func.apply()     }, interval)   } } debounce(apiCall, 3000) 

9. Реализуйте функцию throttle

Решение:

const throttle = (callback, interval) => {   let timerId;   let allowEvents = true;    return function() {     let context = this;     let args = arguments;      if (allowEvents) {       callback.apply(context, args)       allowEvents = false;       timerId = setTimeOut(function(){         allowEvents = true       }, interval)     }   } } 

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

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

Решение:

//С использованием метода setInterval, декоратора throttle и флагов setInterval=>Endpoint=>Render  //с инверсией управления //Endpoint=>Render=>setTimeout=>Endpoint=>Render=>SetTimeout...

11. Конвертируйте этот код, основанный на наследовании классов, в ES5.

class Parent(name){   constructor(name) {     this.name=name   }    getName(){return this.name} }  class Children extends Parent {   constructor(props){     super(props)   } }

Решение:

function Parent(name) {   this.name = name }  Parent.prototype.getName = function() {   return this.name }  function Children(name){   Parent.call(this, name) }  Children.prototype = new Parent() 

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

//Q.1 var x = 1; var y = x;  x = 0; console.log(x, y);  //Q.2 var x = [1]; var y = x;  x = []; console.log(x,y);  //Q.3 function Abc() { console.log(this); }; Abc() new Abc();  //Q.4 var x = 1; var obj = {   x: 2,   getX: function () {     return console.log(this.x);   } };  obj.getX() let a = obj.getX console.log(a)  //Q.5 //Как вывести 2 с использованием переменной a в коде из предыдущего вопроса?  //Q.6 console.log("A"); setTimeout(() => console.log("B"), 0); setTimeout(() => console.log("C"), 0); console.log("D");  //Q.7 setTimeout(function() {   console.log("A"); }, 0); Promise.resolve().then(function() {   console.log("B"); }).then(function() {   console.log("C"); });  console.log("D");  //Q.8 let obj1 = {   a:1,   b:2 }  function mutate(obj) {   obj = {a:4, c:6} }  console.log(obj1) mutate(obj1) console.log(obj1) 

Решение:

//A.1 0 1  //A.2 [] [1]  //A.3 Будет выведен объект window  //A.4 Будут выведены значения 2 и 1  //A.5 a.call(obj);  //A.6 A, D, B , C  //A.7 D, B, C, A  //A.8 { a: 1, b: 2 } { a: 1, b: 2 }

13. Есть массив чисел. Выведите следующие элементы.

const list = [1,2,3,4,5,6,7,8] const filteredArray = list.filter(between(3, 6)) // [4,5]

Решение:

function between(start, end) {   return function (value,index) {     return value>start && value<end   } }

Алгоритмы

1. Рассмотрите последовательность.

A := 1 B := A*2 + 2 C := B*2 + 3 и так далее...

Напишите программу, которая :

  • выводит число, соответствующее определенной букве;

  • для строки, например ‘GREP’, вычисляет сумму чисел, соответствующих буквам строки (т. е. G + R + E + P) из этой последовательности;

  • и находит самую короткую строку, соответствующую большому числу (не больше максимального 32-разрядного целого числа).

Для решения последней задачи можно использовать жадный алгоритм. Числовые значения, соответствующие буквам, должны рассчитываться по мере необходимости. НЕ НУЖНО вычислять их заранее и сохранять в структуре данных.

Решение:

//A = 1 //B = A*2 +2  //C = B*2+ 3 //D = C*2+ 3  var genCharArray = function(charA, charZ) {     var a = [], i = charA.charCodeAt(0), j = charZ.charCodeAt(0);     for (; i <= j; ++i) {         a.push(String.fromCharCode(i));     }     return a; }  var charMap = {}; var charArray = genCharArray('a', 'z');  charArray.forEach(function(char, index){     charMap[char] = Number(index + 1); });   var charSequence = function(char){     if(typeof char==="string"){         char = charMap[char];     }     if(char==1){         return 1;     }else{         return char + 2 * charSequence(char-1);     } }  var input = process.argv[2];  if(input.length===1){     console.log(charSequence(charMap[input])); }else if(input.length>1){     var charTotalSequence = input.split("").reduce(function(acc, curr){          return acc + charSequence(charMap[curr]);     },0);     console.log(charTotalSequence); }

2. Найдите в массиве пару чисел, сумма которых равна заданному числу.

Решение:

let nums = [2, 7, 10, 1, 11, 15, 9] let target = 11 let numsMap = new Map() let pairs = nums.reduce((acc, num) => {   let numToFind = target - num   if (numsMap.get(numToFind)) {     return [...acc, [num, numToFind]]   } else {     numsMap.set(num, true)     return [...acc]   } }, [])  console.log("Pairs ", pairs)

3. Найдите локальный максимум в заданном массиве. Локальный максимум — это элемент, значение которого превышает значения элементов, расположенных справа и слева от него. Я использовал нотацию O(n). Это очевидное решение, которое можно оптимизировать.

Решение:

let x = [1, 2, 3, 5, 4] //Результаты: 5 if x.length == 1 return x[0] else   let i = 1  for(;i<x.length-1;i++){   if x[i-1]<x[i] and x[i] > x[i+1] return x[i]  }  if x.length - 1 == i return x[i]

4. Поверните матрицу на 90 градусов по часовой стрелке. Решение должно выполняться в памяти, содержащей входные данные (алгоритм in-place, «на месте»).

leetcode

Решение:

[  [1, 2, 3],  [4, 5, 6],  [7, 8, 9] ] //Сначала транспонируем матрицу. //После транспонирования матрица будет выглядеть так. [  [1, 4, 7],  [2, 5, 8],  [3, 6, 9] ] //Теперь остается всего лишь изменить порядок элементов массива на обратный. //В результате матрица будет выглядеть так. [  [7, 4, 1],  [8, 5, 2],  [9, 6, 3] ] //Первоначальная матрица развернута на 90 градусов.

5. Максимальная сумма подмассивов по модулю M.

Решение

6. Найдите в массиве три элемента, сумма которых равна заданному числу.

Решение:

let x = [1, 2, 3, 4, 5] let target = 7 let found = []  const twoPointer = (l ,r, current) => {   while(l<r){     const totalSum = current + x[l] + x[r]     if (totalSum === target) {       found.push([current, x[l], x[r]])       return     } else if (totalSum > target) {       r--     } else {       l++     }   } }  const threeSum = (x, target) => {     for (let i=0;i<x.length;i++) {       const current = x[i];       let leftPointer = i+1       let rightPointer = x.length - 1        if (current+x[leftPointer]+x[rightPointer] === target) {         found.push([current, x[leftPointer], x[rightPointer]])       } else {         twoPointer(leftPointer, rightPointer, current)       }   }   return found }

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

ссылка

Решение:

const subStrHasSameCharCount = (str, startIndex, endIndex, totalHop) => {   let charMap = {}   for (let k=startIndex;k<endIndex;k++) {     let currentChar = str[k]     if (charMap[currentChar]) {       charMap[currentChar]++     } else {       charMap[currentChar] = 1     }   }   let totalCount = Object.values(charMap).length > 0   return totalCount ? Object.values(charMap).every(item => item == totalHop) : false }   const characterWithCountK = (str, k) => {   if (k == 0) return ''   let count = 0   let initialHop = k   while (initialHop < str.length) {     for (let j=0;j<str.length;j++) {       let startIndex = j       let endIndex = j + initialHop       if(endIndex > str.length) continue       count = subStrHasSameCharCount(str, startIndex, endIndex, k)         ? count + 1: count     }     initialHop+=k   }   count = subStrHasSameCharCount(str, 0, initialHop, k)         ? count + 1: count   return count }   let str = 'aabbcc' let k = 2 console.log(characterWithCountK(str, k)) 

8. Есть две строки — s1 и s2, каждая из которых содержит символы от a до z в разном порядке. Проверьте, можно ли переставить символы в строке s1 таким образом, чтобы строки стали равными.

Решение:

let s1 = 'dadbcbc' let s2 = 'ccbbdad' let charMap = {}  const canBeRearranged = (s1, s2) => {   if(s1.length!==s2.length){     return false   }   for(let i=0;i<s1.length;i++){     const charFromString1 = s1[i]     const charFromString2 = s2[i]     if(charFromString1 in charMap){       charMap[charFromString1]++     } else {       charMap[charFromString1] = 1     }     if(charFromString2 in charMap){       charMap[charFromString2]--     } else {       charMap[charFromString2] = -1     }   }   for(let x in charMap){     if (charMap[x]!==0){       return false     }   }   return true }  canBeRearranged(s1, s2) 

9. Есть массив с переменной начальной длиной. Расположите элементы массива в случайном порядке.

Решение:

const swap = (index1, index2, arr) => {   let temp = arr[index1]   arr[index1] = arr[index2]   arr[index2] = temp }  const shuffle = (arr) => {   let totalLength = arr.length   while(totalLength > 0) {     let random = Math.floor(Math.random() * totalLength)     totalLength--     swap(totalLength, random, arr)   }   return arr }   let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] arr = shuffle(arr)

10. Вычислите сумму всех элементов многомерного массива с бесконечной глубиной.

Решение:

let arr = [4, 5, 7, 8, [5, 7, 9, [3, 5, 7]]] let sum = 0  const calculateSum = (arr) => {   arr.reduce(function(acc, currentVal) {     const isEntryArray = Array.isArray(currentVal)     if (isEntryArray) {       return acc.concat(calculateSum(currentVal))     } else {       sum+=currentVal       return acc.concat(currentVal)     }   }, []) } calculateSum(arr) console.log(sum) 

11. Сгладьте многоуровневый вложенный объект.

Решение:

const obj = {   level1: {     level2: {       level3: {         more: 'stuff',          other: 'otherz',         level4: {           the: 'end',         },       },     },     level2still: {       last: 'one',     },     am: 'bored',   },   more: 'what',   ipsum: {     lorem: 'latin',   }, };  var removeNesting = function(obj, parent){   for (let key in obj){     if (typeof obj[key] === "object") {       removeNesting(obj[key], parent+"."+key)     } else {       flattenedObj[parent+'.'+key] = obj[key]     }   } }  let flattenedObj = {} const sample = removeNesting(obj, ""); console.log(flattenedObj);

12. Есть данные в формате json, где каждый объект обозначает каталог и может, в свою очередь, содержать другой вложенный объект. Выведите на экран структуру каталога.

Решение

13. Есть массив объектов, содержащих информацию о сотрудниках (у каждого сотрудника есть несколько подчиненных). На основании этих данных постройте иерархию сотрудников.

Решение:

const employeesData = [{   id: 2,   name: 'Андрей (главный технический директор)',   reportees: [6]  }, {   id: 3,   name: 'Алексей (главный операционный директор)',   reportees: [] }, {   id: 6,   name: 'Александр (руководитель инженерной группы)',   reportees: [9]  }, {   id: 9,   name: 'Анатолий (старший инженер)',   reportees: [] }, {   id: 10,   name: 'Антон (генеральный директор)',   reportees: [2, 3], }];  /* A (генеральный директор) ----B (главный технический директор) --------D (руководитель инженерной группы) ------------E (старший инженер-разработчик) ----C (главный операционный директор) */  const findCeo = (currentEmp) => {   let parentEmployee = employeesData.filter(emp => emp.reportees.indexOf(currentEmp.id) > -1)   if (parentEmployee && parentEmployee.length > 0) {     return findCeo(parentEmployee[0])   } else {     return currentEmp   } }  const logHierarchy = (currentEmp, indent) => {   console.log("-".repeat(indent) + currentEmp.name)   indent+=4;   for(let i=0;i <currentEmp.reportees.length;i++) {     let employee = employeesData.filter(emp => emp.id === currentEmp.reportees[i])     logHierarchy(employee[0], indent)   } }  const traverse = (employee) => {   let ceo = findCeo(employee)   logHierarchy(ceo, 0) }  traverse(employeesData[0])

14. Преобразуйте заданную матрицу в спиральную и выведите на экран

const inputMatrix = [   [1, 2, 3, 4,  5],   [6, 7, 8, 9, 10],   [11,12,13,14,15],   [16,17,18,19,20], ]  const exprectOutput = [1,2,3,4,5,10,15,20,19,18,17,16,11,6,7,8,9,14,13,12]

Решение:

function spiralParser(inputMatrix){   const output = [];   let rows = inputMatrix.length;   let cols = rows > 0 ? inputMatrix[0].length : 0;    //singleEmptyRow => Edge case 1 //[]   if (rows === 0) {     return []   }    if (rows === 1) {     //singleElementRowNoCol => Edge case 2 //[[]]     if (cols === 0) {       return []     } else if (cols === 1){       //singleElementRow => Edge case 3 //[[1]]       output.push(inputMatrix[0][0])       return output      }   }    let top = 0;   let bottom = rows - 1;   let left = 0;   let right = cols - 1;   let direction = 0;   //0 => left->right   //1 => top->bottom   //2 => right->left   //3 => bottom->top    while(left <= right && top <= bottom) {     if(direction === 0) {       //left->right       for (let i=left; i<=right;i++) {         output.push(inputMatrix[top][i])       }       top++;     } else if (direction === 1) {       //top->bottom       for (let i=top; i<=bottom;i++) {         output.push(inputMatrix[i][right])       }       right--     } else if (direction === 2) {       //right->left       for (let i=right; i>=left;i--) {         output.push(inputMatrix[bottom][i])       }       bottom--     } else if (direction === 3) {       //bottom->top       for (let i=bottom; i>=top;i--) {         output.push(inputMatrix[i][left])       }       left++     }     direction = (direction + 1) % 4   }   return output; }  console.log(spiralParser(inputMatrix2))

15. Найдите символ с максимальным количеством последовательных вхождений в заданной строке.

let str = 'bbbaaaaccadd'; //Больше последовательных вхождений (4) у символа a

Решение:

//псевдокод maxNow = если длина входной строки равна1 или больше 1 ? 1 : 0 maxOverall = если длина входной строки равна1 или больше 1 ? 1 : 0  для символов входной строки с индексом 1 и больше   если символ равен предыдущему символу     maxNow++ //увеличить на 1     maxOverall = max(maxOverall, maxNow)   иначе если символ не равен предыдущему символу         maxNow = 1

16. Есть массив переменной длины. Переместите все двойки (2) в конец массива.

let inputArr = [2,9,1,5,2,3,1,2,7,4,3,8,29,2,4,6,54,32,2,100] //ouput => [9,1,5,3,1,7,4,3,8,29,4,6,54,32,100,2,2,2,2,2]

Решение:

let slowRunner = 0  for (let fastRunner=0;fastRunner<arr.length;fastRunner++) {   if (arr[fastRunner]!==2 && arr[slow] == 2) {     [arr[fastRunner], arr[slow]] = [arr[slow], arr[fastRunner]]     slowRunner++   } }

17. Выведите список в обратном порядке

//На входе = 1 -> 2 -> 3 -> 4 -> 5 -> 6 //В результате = 1 <- 2 <- 3 <- 4 <- 5 <- 6

Решение:

//псевдокод let current = head let prev = null let next = null  while(current) {   next = current.next   current.next = prev   prev = current   current = next }

18. Реализуйте прямой обход дерева с помощью итераций (без рекурсии)

Решение:

//псевдокод const preorder = (root) => {   let stack = []   stack.push(root)    пока(переменная stack содержит данные) {     let current = stack.pop()     console.log(current.value)     if (current.right) {       stack.push(current.right)     }     if (current.left) {       stack.push(current.left)     }   } }

Задачи

1. Разработайте систему для автоматизации парковки, отвечающую следующим требованиям.

  • Она хранит данные об N автомобилях. Она обрабатывает данные о наличии парковочных мест.

  • Она регистрирует въезжающие и выезжающие автомобили.

  • Автоматизированная система учета автомобилей регистрирует все въезжающие и выезжающие автомобили по следующим данным: регистрационный номер, цвет, парковочное место.

Система должна предоставлять следующую информацию:

  • регистрационные номера всех автомобилей определенного цвета;

  • номер парковочного места автомобиля по регистрационному номеру;

  • парковочные места автомобилей определенного цвета.

  • список свободных парковочных мест.

Требования:

  • для структурирования кода можно пользоваться классами/структурами;

  • решение должно быть расширяемым для последующего применения.

Некоторые принципы разработки кода:

  • модульность кода;

  • соглашения об именовании;

  • принципы SOLID.

Решение

2. Создайте React-компонент Ping, при использовании которого API будет отправлять запрос по заданному URL. Если возвращается код состояния 200, это означает, что пользователь в Сети. Если возвращается любой другой код состояния, это означает, что пользователь не в Сети.

Попробуйте изменить статус из сетевой панели dev tools.

Решение

3. Создайте конструктор динамических форм на базе json. Формы должны группироваться по id. В каждой группе может быть другая вложенная группа.

Решение

4. Создайте на чистом JavaScript простейший лист Excel, в котором можно добавлять и удалять строки и столбцы. На решение этой задачи отводилось 40 минут.

Решение

5. Создайте строку поиска по списку пользователей.

Объект user (пользователь) включает следующие поля.

id: уникальный идентификатор имя: имя пользователя товары: список товаров, заказанных пользователем адрес: адрес пользо индекс: почтовый индекс пользователя

Поиск должен осуществляться по всем полям.

Результаты поиска должны выводиться в виде карточки пользователя.

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

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

(Навигация будет осуществляться с помощью клавиатуры, если мышь наведена на элемент списка. Если клавиатура не используется, навигация будет осуществляться с помощью мыши.)

Это похоже на принцип поиска в YouTube

Если результаты не найдены, выводится пустая карточка.
Список карточек должен прокручиваться.

Подсвеченная карточка (с помощью клавиатуры или мыши) появляется в области просмотра полностью.

Решение

Другие вопросы

1. Как бы вы структурировали интерфейсное приложение? (посмотреть)
2. Реализуйте стратегию ленивой загрузки (посмотреть)
3. Что такое серверный рендеринг?
4. Как развернуть React-приложение в промышленной среде?
5. Что такое сервис-воркер (веб-воркер)?
6. Как оптимизировать веб-приложение и повысить его производительность?
7. Расскажите о стратегиях кэширования на стороне клиента.
8. Что такое CORS?
9. Назовите компоненты высшего порядка в React.
10. Как работает функция connect в Redux?
11. Что такое PureComponent в React?

Ресурсы

ссылка


Узнать подробно о курсе:

ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/517560/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *