- PVSM.RU - https://www.pvsm.ru -
Недавно мне довелось побывать на встрече [1] участников проекта FreeCodeCamp [2] в Сан-Франциско. Если кто не знает, Free Code Camp — это сообщество, нацеленное на изучение JavaScript и веб-программирования. Там один человек, который готовился к собеседованиям на позицию фронтенд-разработчика, попросил меня подсказать, какие вопросы по JavaScript стоит проработать. Я немного погуглил, но не смог найти подходящего списка вопросов, на который я бы мог дать ссылку и сказать: «Разбери эти вопросы и работа твоя». Некоторые [3] списки [4] были [5] близки [6] к тому, что мне хотелось найти, некоторые [7] выглядели [8] очень уж простыми [9], но все они были либо неполными, либо содержали вопросы, которые вряд ли кто станет задавать на реальном собеседовании.
В итоге я решил составить собственный список. В него входят и те вопросы, которые задавали мне, когда я искал работу, и те, которые задавал я, когда искал сотрудников на позиции фронтенд-разработчиков. Обратите внимание на то, что некоторые компании (вроде Google) уделяют особое внимание таким вещам, как проектирование эффективных алгоритмов. Поэтому, если вы хотите в подобной компании работать, в дополнение к приведённым тут вопросам, порешайте задачки с соревнований CodeJam [10].
Я буду добавлять и редактировать ответы на эти вопросы здесь [11]. Если у вас возникнет желание что-нибудь дополнить или улучшить — буду рад вашим пулл-реквестам.
Вопросы разбиты на несколько разделов:
Итак, вот мои вопросы.
Интервьюируемый должен обладать чётким пониманием концепций, которые затрагивают вопросы из этого раздела, должен уметь всё это объяснить. Программирование тут не требуется.
this
?Ответы на эти вопросы предполагают реализацию функций на JavaScript. За каждым вопросом следуют тесты, которые должно успешно проходить решение.
isPrime()
, которая возвращает true
или false
, указывая, является ли переданное ей число простым.
isPrime(0) // false
isPrime(1) // false
isPrime(17) // true
isPrime(10000000000000) // false
factorial()
, которая возвращает факториал переданного ей числа.
factorial(0) // 1
factorial(1) // 1
factorial(6) // 720
fib()
, возвращающую n-ное число Фибоначчи [12].
fib(0) // 0
fib(1) // 1
fib(10) // 55
fib(20) // 6765
isSorted()
, которая возвращает true
или false
в зависимости о того, отсортирован ли переданный ей числовой массив.
isSorted([]) // true
isSorted([-Infinity, -5, 0, 3, 9]) // true
isSorted([3, 9, -3, 10]) // false
filter()
[13].
filter([1, 2, 3, 4], n => n < 3) // [1, 2]
reduce()
[14].
reduce([1, 2, 3, 4], (a, b) => a + b, 0) // 10
reverse()
, которая обращает порядок следования символов переданной ей строки. Не пользуйтесь встроенной функцией reverse()
[15].
reverse('') // ''
reverse('abcdef') // 'fedcba'
indexOf()
[16] для массивов.
indexOf([1, 2, 3], 1) // 0
indexOf([1, 2, 3], 4) // -1
isPalindrome()
, которая возвращает true
или false
в зависимости от того, является ли переданная ей строка палиндромом (функция нечувствительна к регистру и к наличию в строке пробелов).
isPalindrome('') // true
isPalindrome('abcdcba') // true
isPalindrome('abcd') // false
isPalindrome('A man a plan a canal Panama') // true
missing()
, которая принимает неотсортированный массив уникальных чисел (то есть, числа в нём не повторяются) от 1 до некоего числа n, и возвращает число, отсутствующее в последовательности. Там может быть либо одно отсутствующее число, либо их может не быть вовсе.
Способны ли вы добиться того, чтобы функция решала задачу за время O(N)? Подсказка: есть одна хорошая формула, которой вы можете воспользоваться.
missing([]) // undefined
missing([1, 4, 3]) // 2
missing([2, 3, 4]) // 1
missing([5, 1, 4, 2]) // 3
missing([1, 2, 3, 4]) // undefined
sBalanced()
которая принимает строку и возвращает true
или false
, указывая на то, сбалансированы ли фигурные скобки, находящиеся в строке.
isBalanced('}{') // false
isBalanced('{{}') // false
isBalanced('{}{}') // true
isBalanced('foo { bar { baz } boo }') // true
isBalanced('foo { bar { baz }') // false
isBalanced('foo { bar } }') // false
fib2()
. Она похожа на функцию fib()
из предыдущей группы заданий, но поддерживает числа вплоть до 50. Подсказка: используйте мемоизацию.
fib2(0) // 0
fib2(1) // 1
fib2(10) // 55
fib2(50) // 12586269025
isBalanced2()
. Она похожа на функцию isBalanced()
из предыдущей группы заданий, но поддерживает три типа скобок: фигурные {}
, квадратные []
, и круглые ()
. При передаче функции строки, в которой имеются неправильные скобочные последовательности, функция должна возвращать false
.
isBalanced2('(foo { bar (baz) [boo] })') // true
isBalanced2('foo { bar { baz }') // false
isBalanced2('foo { (bar [baz] } )') // false
uniq()
, которая принимает массив чисел и возвращает уникальные числа, найденные в нём. Может ли функция решить эту задачу за время O(N)?
uniq([]) // []
uniq([1, 4, 2, 2, 3, 4, 8]) // [1, 4, 2, 3, 8]
intersection()
, которая принимает два массива и возвращает их пересечение. Можете ли вы добиться того, чтобы функция решала эту задачу за время O(M+N), где M и N — длины массивов?
intersection([1, 5, 4, 2], [8, 91, 4, 1, 3]) // [4, 1]
intersection([1, 5, 4, 2], [7, 12]) // []
sort()
[17], которая сортирует числовой массив за время O(N×log(N)).
sort([]) // []
sort([-4, 1, Infinity, 3, 3, 0]) // [-4, 0, 1, 3, 3, Infinity]
includes()
, которая возвращает true
или false
в зависимости от того, встречается ли переданное ей число в переданном ей отсортированном массиве. Может ли функция решить эту задачу за время O(log(N))?
includes([1, 3, 8, 10], 8) // true
includes([1, 3, 8, 8, 15], 15) // true
includes([1, 3, 8, 10, 15], 9) // false
assignDeep()
, которая похожа на Object.assign()
[18], но выполняет глубокое объединение объектов. Для того, чтобы не усложнять задачу, можно исходить из допущения, что объекты могут содержать только числа и другие объекты (в них не может быть массивов, строк, и так далее).
assignDeep({ a: 1 }, {}) // { a: 1 }
assignDeep({ a: 1 }, { a: 2 }) // { a: 2 }
assignDeep({ a: 1 }, { a: { b: 2 } }) // { a: { b: 2 } }
assignDeep({ a: { b: { c: 1 }}}, { a: { b: { d: 2 }}, e: 3 })
// { a: { b: { c: 1, d: 2 }}, e: 3 }
reduceAsync()
, которая похожа на функцию reduce()
[14] из группы простых заданий, но работает с функциями, возвращающими promise-объекты, каждый из которых должен быть разрешён до перехода к следующему.
let a = () => Promise.resolve('a')
let b = () => Promise.resolve('b')
let c = () => new Promise(resolve => setTimeout(() => resolve('c'), 100))
await reduceAsync([a, b, c], (acc, value) => [...acc, value], [])
// ['a', 'b', 'c']
await reduceAsync([a, c, b], (acc, value) => [...acc, value], ['d'])
// ['d', 'a', 'c', 'b']
seq()
, пользуясь тем же подходом, что и при работе над функцией reduceAsync()
. Эта функция должна принимать массив функций, которые возвращают promise-объекты, и разрешать их один за другим.
let a = () => Promise.resolve('a')
let b = () => Promise.resolve('b')
let c = () => Promise.resolve('c')
await seq([a, b, c]) // ['a', 'b', 'c']
await seq([a, c, b]) // ['a', 'c', 'b']
Некоторые задания из этой группы связаны с созданием структур данных. Не нужно запоминать все тонкости их функционирования, достаточно понимания их устройство, при этом сведения о предоставляемом ими интерфейсе можно найти в интернете. Далее, нужно знать, для чего эти структуры данных используются, каковы их ограничения в сравнении с другими структурами данных.
permute()
, которая возвращает массив строк, содержащий все пермутации заданной строки.
permute('') // []
permute('abc') // ['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
debounce()
[19].
let a = () => console.log('foo')
let b = debounce(a, 100)
b()
b()
b() // только этот вызов должен вызывать a()
LinkedList
[20], не используя встроенные массивы JavaScript ( []
). Ваш LinkedList
должен поддерживать лишь 2 метода: add()
и has()
.
class LinkedList {...}
let list = new LinkedList(1, 2, 3)
list.add(4) // undefined
list.add(5) // undefined
list.has(1) // true
list.has(4) // true
list.has(6) // false
HashMap
[21], не используя встроенные объекты JavaScript ( {}
) или функцию map()
. Вам дана функция hash()
, которая принимает строку и возвращает некое число. Эти числа, в основном, уникальны, но возможна и ситуация, когда двум разным строкам соответствуют одинаковые числа.
function hash (string) {
return string
.split('')
.reduce((a, b) => ((a << 5) + a) + b.charCodeAt(0), 5381)
}
Ваша реализация HashMap
должна поддерживать лишь 2 метода: get()
и set()
.
let map = new HashMap
map.set('abc', 123) // undefined
map.set('foo', 'bar') // undefined
map.set('foo', 'baz') // undefined
map.get('abc') // 123
map.get('foo') // 'baz'
map.get('def') // undefined
BinarySearchTree
. Он должен поддерживать 4 метода: add()
, has()
, remove()
, и size()
.
let tree = new BinarySearchTree
tree.add(1, 2, 3, 4)
tree.add(5)
tree.has(2) // true
tree.has(5) // true
tree.remove(3) // undefined
tree.size() // 4
BinaryTree
, который поддерживает поиск в ширину, а также функции симметричного, прямого и обратного поиска в глубину.
let tree = new BinaryTree
let fn = value => console.log(value)
tree.add(1, 2, 3, 4)
tree.bfs(fn) // undefined
tree.inorder(fn) // undefined
tree.preorder(fn) // undefined
tree.postorder(fn) // undefined
При ответе на следующие вопросы сначала постарайтесь понять, почему представленный код не работает. Объясните причину ошибки. Затем предложите пару вариантов исправления проблемы и перепишите код, реализуя один из предложенных вариантов. В итоге программа должна работать правильно.
hey amy
, но он выводит hey arnold
. Почему?
function greet(person) {
if (person == { name: 'amy' }) {
return 'hey amy'
} else {
return 'hey arnold'
}
}
greet({ name: 'amy' })
0, 1, 2, 3
в указанном порядке, но он этого не делает (Однажды вы столкнётесь с этой ошибкой. Некоторые люди любят задавать этот вопрос на собеседованиях).
for (var i = 0; i < 4; i++) {
setTimeout(() => console.log(i), 0)
}
doggo
, но он выводит лишь undefined
.
let dog = {
name: 'doggo',
sayName() {
console.log(this.name)
}
}
let sayName = dog.sayName
sayName()
bark()
объекта Dog
вызывает ошибку. Почему?
function Dog(name) {
this.name = name
}
Dog.bark = function() {
console.log(this.name + ' says woof')
}
let fido = new Dog('fido')
fido.bark()
isBig()
возвращает именно такой результат?
function isBig(thing) {
if (thing == 0 || thing == 1 || thing == 2) {
return false
}
return true
}
isBig(1) // false
isBig([2]) // false
isBig([3]) // true
Если вы не уверены, что знаете, что такое «проектирование систем», сначала почитайте это [22].
1. Расскажите о реализации виджета автозавершения вводимого пользователем текста. Данные для автозавершения загружаются с сервера. Рассмотрите клиентскую и серверную части системы.
2. Расскажите о реализации сервиса, подобного Twitter, описав клиентскую и серверную части (этот вопрос бессовестно украден у моего друга Майкла Ву [23]).
Надеемся, эти вопросы пригодятся и тем, кто собирается на собеседования, и тем, кто их проводит. А если вы не относитесь ни к тем, ни к другим, полагаем, вопросы помогут вам поддерживать себя в хорошей программистской форме.
Вот, кстати, ещё несколько мест, куда можно заглянуть, если вам хочется попрактиковаться: The Algorithm Design Manual [24], задачи с соревнований CodeJam [10], репозиторий keon/algorithms [25]. А вот — несколько ресурсов, которые будут полезны JS-разработчикам: JavaScript Allonge [26], You Don’t Know JS [27], Effective JavaScript [28].
Уважаемые читатели! Если у вас есть на примете вопросы, которые, по вашему мнению, стоит добавить в этот список (или если вы обнаружите ошибку) — расскажите нам и напишите [29] автору этого материала.
Автор: ru_vds
Источник [30]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/261450
Ссылки в тексте:
[1] встрече: https://www.meetup.com/Free-Code-Camp-SF/
[2] FreeCodeCamp: https://www.freecodecamp.com/
[3] Некоторые: https://github.com/h5bp/Front-end-Developer-Interview-Questions
[4] списки: https://github.com/khan4019/front-end-Interview-Questions
[5] были: https://github.com/kennymkchan/interview-questions-in-javascript
[6] близки: https://medium.freecodecamp.com/3-questions-to-watch-out-for-in-a-javascript-interview-725012834ccb
[7] некоторые: https://medium.com/javascript-scene/10-interview-questions-every-javascript-developer-should-know-6fa6bdf5ad95
[8] выглядели: https://www.toptal.com/javascript/interview-questions
[9] простыми: https://www.codementor.io/nihantanu/21-essential-javascript-tech-interview-practice-questions-answers-du107p62z
[10] CodeJam: https://code.google.com/codejam/past-contests
[11] здесь: https://github.com/bcherny/frontend-interview-questions
[12] число Фибоначчи: https://en.wikipedia.org/wiki/Fibonacci_number
[13] filter()
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Filter
[14] reduce()
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
[15] reverse()
: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse
[16] indexOf()
: https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
[17] sort()
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
[18] Object.assign()
: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
[19] debounce()
: https://lodash.com/docs/4.17.4#debounce
[20] LinkedList
: https://en.wikipedia.org/wiki/Linked_list
[21] HashMap
: https://en.wikipedia.org/wiki/Hash_table
[22] это: https://github.com/donnemartin/system-design-primer
[23] Майкла Ву: https://github.com/blaisebaileyfinnegan
[24] The Algorithm Design Manual: https://smile.amazon.com/Algorithm-Design-Manual-Steven-Skiena/dp/1848000693
[25] keon/algorithms: https://github.com/keon/algorithms
[26] JavaScript Allonge: https://leanpub.com/javascriptallongesix/read
[27] You Don’t Know JS: https://github.com/getify/You-Dont-Know-JS
[28] Effective JavaScript: https://smile.amazon.com/Effective-JavaScript-Specific-Software-Development/dp/0321812182
[29] напишите: mailto:boris@performancejs.com
[30] Источник: https://habrahabr.ru/post/334538/
Нажмите здесь для печати.