October 9
Задачи на собеседование
Теоретическая часть
Браузер:
- Какие процессы происходят в браузере, после получения HTML от сервера и до его парсинга ? (критические этапы рендера)
- В чем разница между Session Storage, Local Storage и cookie ?
- В чем отличие DOM от RenderTree ? Привести примеры, какие сущности могут быть в DOM и отсутствовать в RenderTree, и наоборот.
- Какие стадии распространения события по DOM дереву ты знаешь ?
- Можно ли обработать событие на стадии погружения ?
- Как остановить всплытие события ? (stopPropagation)
- Как остановить любое дальнейшее РАСПРОСТРАНЕНИЕ события ? (stopImmediatePropagation)
Сетевые технологии
- Какие методы HTTP запросов ты знаешь ?
- Что такое REST ?
- Можно ли сказать, что методы - это всего лишь семантика, а не жесткие ограничения ?
- Задача - реализовать чат с обновлением сообщений real-time. Можно ли это сделать с помощью обычного HTTP ? Какими способами это сделать удобнее ?
- Какие группы кодов ответов от сервера ты знаешь ? За что отвечают 300-ые коды ?
- Что такое DNS ?
- Что такое CDN ?
HTML / CSS
- Что такое семантика DOM-элементов ?
- Что такое data-атрибуты ?
- Можно ли использовать в CSS переменные ?
- Какие ты знаешь псевдоклассы ? Какие ты знаешь псевдоэлементы ? А кроме after/before ?
- Какие значения свойства positon ты знаешь ?
- В чем отличие display: none от visibility: hidden ?
- Что такое контекст наложения (stacking context) ? Что кроме z-index создает под собой контекст наложения ?
- Что такое вендорные префиксы (-webkit-, -moz-, -o-) и зачем они нужны ?
Javascript
Области видимости, hoisting, лексическое окружение
let value = 2; function showValue() { console.log(`showValue ${value}`); } function wrapper() { var value = 3; console.log(`wrapper ${value}`); showValue(); } wrapper(); - ?
var foo = 123; if (true) { var foo = 456; } console.log(foo); - ?
Контекст функций
var side = 20; const square = { side: 5, area() { return this.side * this.side; }, perimeter: () => 4 * this.side }; console.log(square.area()); - ? console.log(square.perimeter()); - ?
var side = 20; const square = { side: 5, area() { return this.side * this.side; }, perimeter: () => 4 * this.side }; const area = square.area; console.log(area()); - ?
var side = 20; const square = { side: 5, area() { return this.side * this.side; }, perimeter: () => 4 * this.side }; function foo(cb) { console.log(cb()) } foo(square.area)
var side = 20; const square = { side: 5, area() { return this.side * this.side; }, perimeter: () => 4 * this.side }; const area = square.area.bind(square).bind({ side: 7 }); console.log(area()); - ?
Event Loop
setTimeout(() => console.log(2), 0); console.log(1); new Promise(res => { console.log(6); res(); console.log(3); }).then(() => console.log(4)); console.log(5);
setTimeout(() => console.log(0), 3000); console.log(1); new Promise(async (resolve, reject) => { console.log(2); resolve(3); const promise = new Promise((resolve, reject) => { setTimeout(() => { new Promise((resolve, reject) => { reject(4); console.log(5) }) .catch(console.log) console.log(6) }, 0) resolve(7) }) await promise.then(console.log) console.log(8) }) .then((res) => console.log(res)) .catch((error) => console.log(error)) console.log(9);
Promise
Promise.resolve(1) .then(x => x + 1) .then(x => { throw x }) .then(x => console.log(x)) .catch(err => { console.log(err); return; }) .finally(res => console.log(res)) .then(x => Promise.resolve(1)) .catch(err => console.log(err)) .then(x => console.log(x));
Прототипы
// Реализовать customMap, который полностью повторяет функционал // нативного Array.map const arr = [1, 2, 3, 4, 5] const multipleArr = arr.customMap((item) => item * 2) console.log(multipleArr) // [2, 4, 6, 8, 10]
const obj = Object.create(null) console.log(obj.hasOwnProperty('__proto__'))
Typescript
const a = 2; const b = 3; const logger = (c: typeof b) => { console.log(c); } logger(2);
// Типизировать функцию test любым способом const test = () => { } test('test string'); // ✅ test(2, 3); // ✅ test('str', 3) // ❌ test(3, 'str') // ❌ test('str', 'str') // ❌ test(3) // ❌
type NonNegativeInteger = const a: NonNegativeInteger = 42; // OK const b: NonNegativeInteger = 0; // OK const c: NonNegativeInteger = -10; // Error
React
// Что произойдет при клике по кнопке? export default function Counter() { let count = 0; const changeCount = () => { count += 1; } return ( <div> <h1>Counter</h1> <div>{count}</div> <button onClick={ changeCount }>Change count</button> </div> ); }
const CounterContext = createContext(null); const B = ({counter}) => { const counterFromContext = useContext(CounterContext) return ( <> <div>{counter}</div> <div>{counterFromContext}</div> </> ) } // Сколько рендеров А и B будет при нажатии на кнопку? const A = () => { const [counter, setCounter] = useState(0); return ( <CounterContext.Provider value={counter}> <button onClick={() => setCounter((prev) => prev + 1)}>Click me</button> <B counter={counter} /> </CounterContext.Provider> ) }
const CounterContext = createContext(null); const B = ({counter}) => { const counterFromContext = useContext(CounterContext) return ( <> <div>{counter}</div> <div>{counterFromContext}</div> </> ) } const A = () => { const [counter1, setCounter1] = useState(0); const [counter2, setCounter2] = useState(0); // Поменяется ли количество рендереов в таком случае? const handleClick = () => { setCounter1((prev) => prev + 1) setCounter2((prev) => prev + 1) } return ( <CounterContext.Provider value={counter2}> <button onClick={handleClick}>Click me</button> <B counter={counter1} /> </CounterContext.Provider> ) }
export default function App(props) { // Реализовать хук useFirstRender const isFirstRender = useFirstRender(); if(isFirstRender) return null; return props.children }
export default function PreviousComponent() { const [number, setNumber] = useState(0); // Реализовать хук usePrevious const previousNumber = usePrevious(number); return ( <div> <p>previousNumber: {previousNumber}</p> <p>currentNumber: {number}</p> <button onClick={() => setNumber(Math.floor(Math.random() * 100))}> Random number </button> </div> ) }
// Указать неточности и то что можно было бы исправить. import React from "react"; const pleaseReviewMe = () => { const [count, setCount] = React.useState(1); const [items, setItems] = React.useState([{ id: 1 }]); React.useLayoutEffect(() => { setInterval(() => console.log(count), 1000); }); const click = React.useCallback(() => { setCount(count + 1); setItems([...items, { id: count + 1 }]); } ); return ( <React.Fragment> <ul> {items.map((item) => ( <li key={Math.random()}>{item.id}</li> ))} </ul> <button key='button' onClick={() => click()}>add one</button> </React.Fragment> ); }; export default PleaseReviewMe;
// Указать неточности и то что можно было бы исправить. import React from 'react'; const pleaseReviewMe = () => { const [name, setName] = React.useState(''); const [user, setUser] = React.useState({ name: '' }); const [items, setItems] = React.useState([]); const [count, setCount] = React.useState(0); React.useLayoutEffect(() => { fetch('https://jsonplaceholder.typicode.com/users') .then((response) => response.json()) .then((data) => setItems(data)) .catch((error) => console.log(error)); }); React.useEffect(() => { setUser({ name }); }, [name]); const click = () => { setCount(count + 1); setTimeout(() => { console.log(`Вы кликнули ${count + 1} раз`); }, 300); }; return ( <div style={{ padding: '20px', color: 'blue' }}> <h2>Привет, {user.name}!</h2> <button onClick={click}>Кликни для счетчика</button> <input value={name} placeholder='Введи имя' onChange={(e) => setName(e.target.value)} /> <p>Счетчик кликов: {count}</p> <p>Список всех пользователей с сервера:</p> <ul> {items.map((item) => ( <li key={Math.random()}>{item.name}</li> ))} </ul> </div> ); }; export default PleaseReviewMe;
Лайв-кодинг
Анаграммы (Junior/Middle-)
Задача - http://jsbin.com/fuvawuk/6/edit?js,output
Решение - https://jsbin.com/cujiqocopo/edit?js,output
Сортировка и группировка (Junior/Middle-)
Задача - http://jsbin.com/noracaq/5/edit?js,output
Решение - https://jsbin.com/zadazuduto/edit?js,output
Шпион (Middle/Middle+)
Задача - http://jsbin.com/kohaxip/4/edit?js,output
Решение - https://jsbin.com/xokijigaye/edit?js,output
Банкомат (Middle/Senior)
Задача - https://jsbin.com/kiwuxig/edit?js,output
Решение - https://jsbin.com/caraxexozi/edit?js,output
Цепочка промисов (Junior)
Задача - http://jsbin.com/kiyipop/3/edit?js,output
Решение - https://jsbin.com/dusibozone/edit?js,output