Skip to content

Instantly share code, notes, and snippets.

@egorzekov
Last active May 18, 2018 06:40
Show Gist options
  • Save egorzekov/3501b1f0a4596d6c0b7d08accfea90aa to your computer and use it in GitHub Desktop.
Save egorzekov/3501b1f0a4596d6c0b7d08accfea90aa to your computer and use it in GitHub Desktop.
Interview preparation
/*
Типы данных в JS. Приведение типов
*/
// primitives
const someString = 'some_string',
someNumber = 12345,
someBoolean = true,
someUndefined = undefined,
someNull = null;
// object
const someObject = { a: 'a' };
typeof someString; // 'string'
typeof someObject; // 'object'
typeof null; // 'object' - language error
typeof function() {}; // 'function'
/*
Что такое hoisting?
*/
// Всплытие объявления переменных вверх. Пример:
console.log(a); // undefined
console.log(b); // function body
console.log(c); // undefined
b() // 'b function'
c() // TypeError - not a function (it's undefined)
var a = 2;
// Function Declaration
function b() {
console.log('b function');
}
// Function Expression
var c = function() {
console.log('c function');
}
console.log(a); // 2
console.log(b); // function body
console.log(c); // function body
b() // 'b function'
c() // 'c function'
/*
Let vs var. Const
*/
// ES6 (es-2015) ключевые слова для объявления переменных
// 1. Область видимости переменной let, const – блок {...}.
{
var a = 'a';
}
console.log(a); // 'a'
{
let b = 'b';
}
console.log(b); // ReferenceError
// 2. Переменная let видна только после объявления (no hoisting).
console.log(a); // undefined
var a = 'a';
console.log(b); // ReferenceError
let b = 'b';
// 3. При использовании в цикле, для каждой итерации создаётся своя переменная.
// 4. Объявление const задаёт константу, то есть переменную, которую нельзя менять.
// Т.е. нельзя менять ссылку, но если это объек или массив - можно менять свойства внутри.
const c = {};
c = 'c'; // TypeError: Assignment to constant variable.
c.someKey = 'c';
console.log(c); // { someKey: "c" }
/*
Что такое this?
*/
// Значение this называется контекстом вызова и будет определено в момент вызова функции.
// https://learn.javascript.ru/object-methods#%D0%BF%D0%BE%D0%B4%D1%80%D0%BE%D0%B1%D0%BD%D0%B5%D0%B5-%D0%BF%D1%80%D0%BE-this
/*
Apply, call, bind. Для чего используются? В чем отличия?
*/
function show(amount, currency) {
console.log(this);
console.log(this.name);
console.log(`${this.name} has ${amount} ${currency}`);
}
show(12, 'USD') // ' has 12 USD' - this ссылается на глобальный объект window
// 1. Call - явный вызов функции с новым контекстом. Дополнительные аргументы передаются СПИСКОМ.
show.call({ name: 'Egor' }, 50, 'USD'); // 'Egor has 12 USD' - this ссылается на переданный объект { name: 'Egor' }
// 2. Apply - явный вызов функции с новым контекстом. Дополнительные аргументы передаются МАССИВОМ.
show.apply({ name: 'Egor' }, [50, 'USD']); // 'Egor has 12 USD' - this ссылается на переданный объект { name: 'Egor' }
// 3. Bind - привязка нового контекста к функции. Возвращает новую функцию.
const newShow = show.bind({ name: 'Egor' }) // привязываем новые контекст и сохраняем полученную функцию
newShow(50, 'USD'); // 'Egor has 12 USD' - this ссылается новый контекст
/*
Замыкание. Приведите пример.
*/
// Объявленное внутри - снаружи недоступно, в то время как объявленное снаружи - доступно внутри (Lexical scoping).
// Функции, которые используют переменные из внешнего скоупа - это и есть замыкание (function + env).
// https://www.youtube.com/watch?v=71AtaJpJHw0
function sumOfNumbers(passedOne) {
const outer = 3;
return function(passedTwo) {
return passedOne + outer + passedTwo; // outer и passedOne берутся из замыкания
}
}
console.log(sumOfNumbers(2)(1)); // 6
/*
Sum(1)(2)
*/
function sum(passed) {
return function(inner) {
return passed + inner;
}
}
/*
Prototype. Отличия proto от prototype. Пример наследования
*/
// 1. Объект, на который указывает ссылка __proto__, называется «прототипом».
// Другими словами, прототип – это «резервное хранилище свойств и методов» объекта, автоматически используемое при поиске.
// 2. prototype - старое св-во, которое работает во всех браузерах. proto в конструкторе не работает в IE 10.
// Оно по факту отрабатывает во время создания объекта через new SomeObject.
var animal = {
eats: true
};
function Dog(isCorgy, name) {
this.isCorgy = isCorgy;
this.name = name;
}
Dog.prototype = animal;
var bobby = new Dog(true, 'Bobby');
console.log(bobby.eats);
//3 Examples
var animal = {
eats: true
};
var rabbit = {
jumps: true,
__proto__: animal
};
// obj.hasOwnProperty(prop) - проверка, есть ли св-во в самом объекте (без поиска в прототипах)
console.log(rabbit.hasOwnProperty('jumps')); // true
console.log(rabbit.hasOwnProperty('eats')); // false
//
/*
Как создать объект без прототипа?
*/
// Создание объекта без прототипа резонно, когда названия св-в - динамичны, и могут, например, приходить от пользователя.
// На этой почте могут быть конфликты с дефолтными св-вами и методами объекта.
// 1
Object.create(null);
// 2
let a = {};
a.__proto__ = null;
/*
Методы массива, перебирающие элементы массива
*/
Array.prototype.forEach;
Array.prototype.map;
Array.prototype.filter;
Array.prototype.sort;
Array.prototype.find;
Array.prototype.every;
Array.prototype.some;
/*
“hello world”.repeating(3) -> hello world hello world hello world. Как реализовать?
*/
// Built-in
String.prototype.repeat;
// Common style
String.prototype.repeating = function(number) {
return new Array(number + 1).join(this);
};
// Arrow function style
String.prototype.repeating = (number) => new Array(number + 1).join(this);
/*
Браузерные события элементов. Отмена дефолтных событий браузера
*/
// 1. EVENTS
// Mouse: click, contextmenu, mouseover, mousedown, mouseup, mousemove
// Form: submit
// Iput: focus
// Keyboard: keydown, keyup
// Content: DOMContentLoaded
// Любое событие может иметь обработчик. Они добавляются:
// а. С помощью HTML атрибута (не рекомендуется - разделение ответственности, не знают о перехвате)
//<input type="button" onclick="alert('Клик!')" value="Кнопка"/>
// б. С помощью свойства DOM-объекта (не рекомендуется - можно повесить только один обработчик, не знают о перехвате)
document.getElementById('someButton').onclick = function() {
console.log('Clicked');
};
// в. С помощью addEventListener и removeEventListener интерфейса (современный способ)
function clickHandler() {
console.log('Clicked');
}
document.getElementById('someButton').addEventListener('click', clickHandler);
document.getElementById('someButton').removeEventListener('click', clickHandler);
// В IE8 - это соотв. методы attachEvent и detachEvent, но в них нет контекста.
// Отмена дефолтных событий браузера
// a. event.preventDefault();
// б. вернуть false;
// в. в EI8 - event.returnValue = false;
/*
Всплытие и перехват событий
*/
// Кликая по некому вложенному элементу, помимо запуска его обработчка, будут вызваны обработчики всех его родительских элементов (если у них есть обработчики).
// Стандарт выделяет 3 стадии прохода события:
// Перехват - событие идёт сверху (от родителей) вниз (к ребёнку, который являтся целью).
// Цель - событие достигло целевого элемента, идёт его обработка.
// Всплытие - событие идёт сверху (от родителей) вниз (к ребёнку, который являтся целью).
// Чтобы поймать событие на стадии перехвата, нужно использовать третий аргумент addEventListener:
// a. Если аргумент true, то событие будет перехвачено по дороге вниз.
// b. Если аргумент false, то событие будет поймано при всплытии.
// Каждый обработчик имеет доступ к свойствам события:
event.target // самый глубокий элемент, на котором произошло событие.
event.currentTarget // (=this) - элемент, на котором в данный момент сработал обработчик (до которого «доплыло» событие).
/*
Делегирование. Пример
*/
// Делигирование отлично подходит, если есть много элементов, обработка которых очень схожа.
// Алгоритм:
// 1. Вешаем обработчик на контейнер.
// 2. В обработчике: получаем event.target.
// 3. В обработчике: если event.target или один из его родителей в контейнере (this) – интересующий нас элемент – обработать его.
`
<div id="menu">
<button data-action="save">Сохранить</button>
<button data-action="load">Загрузить</button>
<button data-action="search">Поиск</button>
</div>
`
var actionMapping = {
save: function() {},
load: function() {},
search: function() {},
};
document.getElementById('menu').addEventListener('click', function() {
const action = event.target.dataset.action;
if (action) {
actionMapping[action]();
}
});
/*
Напишите функцию F, так чтобы new F === F
*/
// 1
const f = function() {};
console.log(f === f); // true
// 2
function F() {
if (!F.instance) {
F.instance = this
}
this.x = 'x';
return F.instance;
}
console.log(F === F); // true
console.log(new F() === new F()); // true
const a = new F();
const b = new F();
console.log(a === b); // true
/*
Function.prototype.bind polyfill
*/
Function.prototype.bind = Function.prototype.bind || function() {
const fn = this;
const args = Array.prototype.slice.call(arguments);
const newContext = args.shift();
return function() {
return fn.apply(newContext, args);
};
};
/*
Object.create polyfill
*/
Object.create = Object.create || function(parent, props) {
function F() {
F.prototype = parent;
if (typeof 'props' === 'object') {
for (prop in props) {
if (props.hasOwnProperty(prop)) {
F[prop] = props[prop];
}
}
}
}
return new F();
};
/*
Event loop
*/
// HEAP - memory allocation
// CALL STACT - execution contexts
// WEB (C++) APIs - do some work in paralel and send to CALLBACK QUEUE
// CALLBACK (TASK) QUEUE - queue of items should be executed once stack gets empty
// EVENT LOOP - If stack is empty and callback queue is not, take the first item from the queue and push to the stack.
// Филип Робертс - What the heck is the event loop anyway? JSconf 2014
// https://www.youtube.com/watch?v=8aGhZQkoFbQ
/*
Promises
*/
// https://www.youtube.com/watch?v=vNEDPtVchfw
// https://www.youtube.com/watch?v=SjNmkeUpQAU&t
// 3 состояния - pending, resolved, rejected
function applyForVisa(documents) {
console.log('Обработка заявления на визу');
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve({ visa: 'someVise' });
}, 2200)
});
}
function getVisa(visa) {
console.log('Виза получена');
return new Promise(function(resolve, reject) {
resolve(visa);
});
}
function bookHotel(visa) {
console.log('Бронируем отель');
return {};
}
function buyTickets(booking) {
console.log('Покупаем билеты');
}
applyForVisa('')
.then((visa) => console.log(visa))
.then(bookHotel)
.then(buyTickets)
.catch(err => console.log(err));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment