Ford's Garage

Small garage of one Ford in the big internet


Front-end developer


Общие вопросы

Жизненный цикл JavaScript-приложения

Нужно рассказать как работает JavaScript-приложение. Каждая вкладка браузера ‒ это отдельное приложение. Рендеринг страницы и интрепретация JavaScript происходит в одном потоке, в основном цикле приложения, а значит ресурсоемких операций следует избегать. Следует упомянуть про событийную модель, про то, что она работает на неблокирующих сокетах (в т.ч.). Тут еще можно вспомнить про requestAnimationFrame.

EcmaScript

Что это? спецификация и язык Какая спецификация является текущей? ECMAScript 2022 Какие существуют различия между ними? зачет ‒ вспомнить про const, let, классы, приватные методы, генераторы, Map, Set и т.п.

JSON

Что такое JSON? JavaScript Object Notation ‒ представление данных, которое является валидным JS кодом Какие существуют функции для работы с JSON? JSON.parse, JSON.stringify Почему нельзя просто использовать eval? Для чего используется? В этом формате хранятся конфиги, а так же отдается ответ сервера в AJAX-приложениях

SPA (Single Page Application)

Что это? Как оно работает? Что такое Rest API? Какие есть приницпы проектирования Rest API? Какие есть стандарты? JSON API Какие есть альтернативы? SOAP, JSON RPC, GraphQL, Protocol Buffers

JavaScript

Задания выполняются на листке/доске, без компа.

Строгое сравнение

Почему всегда нужно использовать строгое сравнение (===)?

Пример:


0 == false // true
[42] == '42' // и т.п.

Определение типа объекта

Чем плохи typeof и instanceof?

typeof null === "object" // true
42 instnaceof Number // false
Напишите функцию isPlainObject(o)

const isPlainObject = o => Object.prototype.toString.call(o) === '[object Object]'

NaN

Что такое? Not A Number Как получить такое значение? 'foo' / 2 Как проверить? isNan

typeof NaN // "number" охуенно?

Еще про типы

Чему равен аргумент функции по-умолчанию? undefined Как проверить является ли значение массивом? Array.isArray Что будет если поделить число на 0? Вселенная взорвется наху… Infinity вернет Как проверить является ли число конечным? isFinite Как проверить является ли число целым? Number.isInteger Являеются ли строки мутабельными? нет При передачи строки в функцию она передается по ссылке или по значению? по ссылке

Копирование объектов

Чем отличается передача объекта по ссылке от передачи по значению? Какие объекты передаются по значению? Задание: напишите самую простую реализацию функции copy(o: <any>) для копирования объекта произвольной вложенности.

function copy(o) {
 return JSON.parse(JSON.stringify(o))
}

var vs const vs let

Чем отличается var от const и let? у const и let область видимости ограничена фигурными скобками {} значение, объявленное через const, нельзя присвоить повторно

{
 let x = 42
}
console.log(x) // что выведет?
Приведет к ошибке: Uncaught ReferenceError: x is not defined

const arr = []
arr.push(42) // Какую ошибку сгенерирует?
Ошибки не произойдет Как сделать объект (массив, например) иммутабельным (неизменяемым)? Object.freeze(o) // Не знает и ладно, потом прочитает.

Замыкания

Классика. На любом собеседованиии задают такой вопрос.

Есть такой код:

for (var i = 0; i < 10; i++) {
 setTimeout(() => console.log(`i=${i}`), 3000)
}
Что будет выведено?
«i=10» 10 раз. Почему так происходит? Как исправить?

for (let i = 0; i < 10; i++) {
 setTimeout(() => console.log(`i=${i}`), 3000)
}
А как бы вы переписали этот код с использованием ES2015?

for (var i = 0; i < 10; i++) {
 setTimeout(function (i) {
 console.log('i=' + i)
 }(i), 3000)
}

Строгий режим

Что означает строка 'use strict' в начале скрипта либо в начале тела функции? включает строгий режим Что происходит при его включении? бросаются исключения, например, при попытке присвоить значение ранее необъявленной переменной (в обычном все ок)

Контекст this

Что выведет этот код?

'use strict'

const test = {
 prop: 42,
 meth() {
 return this.prop
 }
}

const fn = test.meth
console.log(fn())
Будет сгенерирована ошибка TypeError. На что ссылается this в этом примере? window Можно спросить почему так происходит ответ Как исправить?

Вариант 1 (его должны обязательно указать):


const fn = test.meth.bind(test)
    

Вариант 2:


const fn = () => test.meth()
    
Так же можно спросить чем отличаются стрелочные функции от анонимных и в чем их преимущество Cтрелочные функции захватывают контекст this

Обмен значениями

Данные две переменные x = 3 и y = 5.

Как обменять их значения без вспомогательных переменных?

[ x, y ] = [ y, x ]

Правильным так же является и ответ типа такого:


x = x ^ y
y = x ^ y
x = x ^ y
    

Но он для надмозгов.

Спреды

Как используются спреды? (что это я и сам затруднюсь ответить)

// При объявлении функции с произвольным количеством аргументов
function foo(...args) {
 console.log(args)
}

foo(1, 2, 3) // args будет содержать массив [1, 2, 3]

// Спреды можно использовать при передаче списка аргументов
Math.max(...[3, 5, 1])

// Является альтернативой использованию метода функции apply
Math.max.apply(null, [3, 5, 1])

const [ first, ...rest ] = [1, 2, 3, 4, 5]
console.log(first) // содержит 1
console.log(rest) // [2, 3, 4, 5]
    

Колбеки

Что такое функция-обработчик, передаваемая в функцию в качестве аргумента и вызываемая внутри этой фунгкции с передачей ей результата выполнения какой-то асинхронной операции Что такое callback-hell? множество вложенных колбеков Как избежать его использование промисов

Promises

Что такое Promise? Это бъект, которые позволяет обрабатывать результаты асинхронны операций в будущем. Для чего нужны async/await?

Напишите асинхронную функции sleep вида:

function sleep(timeout) {
 [some code]
}

// Пример использования
async run() {
 console.log('Ждем 3 секунды')
 await sleep(3000)
 console.log('Продолжаем работу...')
}
    

function sleep(timeout) { 
    return new Promise((resolve, reject) => setTimeout(resolve, timeout)) 
}
    

Генераторы

Что такое генераторы? Это функции, которые приостанавливают свое выполнение в определенной точке и при последующих вызовах продолжает выполнение с этой точки.

Общий вид:


function* g() {
 yield 'foo'
 yield 'bar'
 yield 'baz'
}
    
Что возвращает функция генератор? итератор Что делает оператор yield? приостонавливает выполнение функции и возвращает значение, но в отличии от return при последующем вызове функции продолжает работу с места остановки С помощью какого метода можно получить текущее значение итератора? next Что он возвращает? объект вида: { value: <any>, done: <bool> } Какая конструкция используется для цикла по итератору?

Ответ:


for (let it of g()) {
 // ...
}
    

Задание: напишите с использование генераторов функцию, возвращающую числа Фиббоначи.

Ряд Фиббоначи выглядит следующим образом:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, …

В нем каждое последующее число равно сумме двух предыдущих.


function* fib() {
     let [ cur, next ] = [ 0, 1 ]
     for (;;) {
         yield cur
         ;[ cur, next ] = [ next, cur + next ]
     }
}
    

Fetch?

Что делает функция fetch? Возвращает Promise и делает запрос. В чем ее преимущество по сравнению с XMLHttpRequest? коротко: более богатый API

ООП

Нет ни одного js-кодера, который не пытался написать свой eventEmitter.

Напишите class EventEmitter

class EventEmitter {
    // ...
    on(event, listener) {
        // ...
    }
    off(event, listener) {
        // ...
    }
    emit(event, ...args) {
        // ...
    }
}

const events = new EventEmitter()
events.on('greeting', name => {
    console.log(`Hello ${name}!`);
})
events.emit('greeting', 'Sergey')

class EventEmitter {
    // Приватные методы (NEW)
    // Используем Map вместо Plain Object, 
    // так как у первого ключами могут быть любые объекты, а не только строки +
    // не нужна проверка hasOwnProperty
    #listeners = new Map()

    on(event, listener) {
        let listeners = this.#listeners.get(event)
        if (!listeners) {
            // Используем Set вместо Array, чтобы нельзя было добавить один и тот же 
            // обработчик два раза
            listeners = new Set()
            this.#listeners.set(event, listeners)
        }
        listeners.add(listener)
        return this
    }
    off(event, listener) {
        const listeners = this.#listeners.get(event)
        if (listeners) {
            listeners.delete(listener)
            // Если листенеров больше не осталось, то нужно удалить ключ
            if (listeners.size === 0) {
                this.#listeners.delete(event)
            }
        }
        return this
    }
    emit(event, ...args) {
        const listeners = this.#listeners.get(event)
        if (listeners) {
            for (const listener of listeners) {
                listener(...args)
            }
        }
        return this
    }
}
Для чего нужен super? Как вызвать родительский конструктор? super([args]) в методе construct класса наследника Как обратиться к родительскому методу? super.meth Что такое геттеры и сеттеры? Как происходит наследование? extends Как сделать метод статическим? static

Сессии

Что такое cookies? небольшие порции данных, которые хранятся на стороне клиента Как установить cookie со значением foo=bar на неопределенный срок?
document.cookie = 'foo=bar'
Как получить все куки в виде объекта (ассоциативного массива)?

// Такой вариант
const c={}
document.cookie.split('; ').forEach(pair => {
 const [ k, v ] = pair.split('=')
 c[decodeURIComponent(k)] = decodeURIComponent(v) 
})
console.log(c)
// Тру функицональщина
document.cookie.split('; ').reduce((acc, pair) => {
 const [ k, v ] = pair.split('=', 2).map(decodeURIComponent)
 acc[k] = v
 return acc
}, {})

// С циклами не айс
    
Как еще можно хранить сессионные данные на стороне клиента? localStorage Что такое JWT? JSON Web Tokens ‒ токены, хранящиеся на стороне клиента. Такой токен состоит из трех частей: заголовков, тела и сигнатуры. В теле хранятся сессионные данные (обычно идентефикатор пользователя). Сигнатуру нельзя подделать не зная секретного ключа (который хранится на сервере).

Модули

Какие ключевые слова используется при работе с модулями? import/export Нужно привести примеры:

// Если функция экспортируется так
export const func = () => {}

// То ее импорт выглядит так
import { func } from './lib'

// Можно импортировать под другим именем
import { func as name } from './lib'

// Можно импортировать все под определенным неймспейсом
import { * as lib } from './lib'

// Нужно упомянуть про export default
export default ...

// При его использование импортировать можно только так
import lib from './lib'
    
Можно ли использовать import/export в браузере без компиляторов типа Babel? Да

<script type="module" src="main.js"></script>
    
В main.js можно испортировать уже привычным образом.

DOM

Что такое DOM? Это представление документа в виде дерева узлов. Каждый узел представляет собой элемент определенного типа (элемент, текст, комментарий, атрибут, документ, фрагмент и т.д.). Узлы содержат ссылки на детей и родителей. Какие существуют методы для поиска элементов на странице с помощью CSS-селекторов [ Document | Element ].querySelector
[ Document | Element ].querySelectorAll

Как с помощью querySelector выбрать вторую колонку таблицы со значением Second?


<!doctype html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
</head>

<body>
  <table>
    <tr>
      <td>First</td>
      <td>Second</td>
      <td>Third</td>
    </tr>
  </table>
</body>

</html>

document.querySelector('td:nth-child(2)')
    
А как сделать тоже самое, но без querySelector?

document.getElementsByTagName('td')[1]
    

Vue

Что такое виртуальный DOM (VDOM)? Суть: позволяет избежать повторного построения DOM-дерева, если данные (модель) не изменились Two-Way Binding. Что это? Это механизм, позволяющий синхронизировать изменения модели и представления. https://gist.github.com/s3rgeym/c45e35634df47fbfebb6f267a126dd4e