Javascript вопросы на собеседовании. Чему равно foo.x? Что выведет alert(NaN === NaN);
Сколько угодно.
- Нужно алертом вывести какое-то сообщение, спустя 3 секунды после запуска скрипта. Как это сделать?
Так:
Или так:
- Чем отличается наследование в JavaScript от наследования в PHP?
В отличие от PHP, где наследование можно делать одним способом, в JavaScript таких способов много. На уровне языка реализовано наследование на прототипах.
В JavaScript каждый объект может иметь ассоциацию с другим объектом - так называемый "прототип" (prototype). В случае, если поиск некоторого свойства (или метода) в исходном объекте заканчивается неудачно, интерпретатор пытается найти одноименное свойство (метод) в его прототипе, затем - в прототипе прототипа и т. д. К примеру, если мы затребовали обращение к obj.prop (или, что абсолютно то же самое, obj["prop"]), JavaScript начнет искать свойство prop в самом объекте obj, затем – в прототипе obj, прототипе прототипа obj, и так до конца.
- Приведи пример наследования в JavaScript.
Например, пусть объект "cat" наследуется от объекта "animal". В наследовании на прототипах это реализуется как ссылка
Или вот чуть более развернутый пример. MyType наследуется от Obj:- Пара слов об объектах в JavaScript?
Объекты (они же - ассоциативные массивы, хэши) и работа с ними в JavaScript реализованы не так, как в большинстве языков. Объект в JavaScript представляет собой обычный ассоциативный массив или, иначе говоря, "хэш". Он хранит любые соответствия "ключ => значение" и имеет несколько стандартных методов.
- Что представляет из себя метод объекта в JavaScript?
Метод объекта в JavaScript - это просто функция, которая добавлена в ассоциативный массив.
- Зачем в JavaScript перед переменной писать var?
Если создавать переменную через обычное присваивание - будет создана "глобальная переменная". Пример:
Если создавать переменную с использованием слова var, тогда будет создана "локальная переменная", которая перестаёт существовать после завершения работы функции.
Пример:
- Есть две функции: function f(a,b) { return a+b } и var f = function(a,b) { return a+b }. Есть ли между ними разница? Если есть то какая?
Есть, разница в видимости функции. Вариант функции без var виден везде в текущей области видимости. В том числе и до самого определения функции. Вариант с var присваивает функцию переменной, поэтому такая функция видна только после определения.
- Как создать массив в JavaScript?
Вот несколько способов.
- Можно ли в JavaScript использовать функцию в качестве конструктора?
Вот так:
- Сколько и какие конструкции для циклов есть в JavaScript?
Три: for, while и do...while.
- Что cделает код: break mark; ?
Выйдет из текущего блока цикла или switch на метку " mark ".
- Можно ли задать массив таким образом: var a = "a,b".split(",")?
Да, можно.
- Что выведет alert(typeof null); ?
Выведет сообщение "object".
- А это: alert(null instanceof Object); ?
Выведет сообщение "false".
- 0.1 + 0.2 == 0.3 ?
Нет, т.к. вычисленное значение будет равно 0.30000000000000004. Это действие точности вычислений и проявляется она не только в JavaScript.
- Что выведет alert(typeof NaN); ?
"Number"
- Что выведет alert(NaN === NaN); ?
"false"
- В чём различие свойств innerHTML и outerHTML?
Свойство любого DOM элемента innerHTML содержит HTML код, который находится внутри этого элемента. При установке нового значения этого свойства, внутренний HTML код рендерится браузером заново.
outerHTML почти аналогичен innerHTML, разница в том, что он возвращает полный HTML элемента.
Также, важно отметить, что innerHTML поддерживается всеми современными браузерами, а outerHTML поддерживается в IE (с некоторыми отличиями от остальных браузеров), в последних версиях Opera, и в браузерах на основе последних WebKit (Safari, Chrome), но не поддерживается в Firefox.
Для кода:
innerHTML возвратит:
outerHTML возвратит:
- Какая разница между операторами == и ===?
Оператор == сравнивает на равенство, а вот === сравнивает на идентичность. Плюс оператора === состоит в том, что он не приводит два значения к одному типу. Именно из-за этого он обычно и используется.
- В чем разница между Object.getOwnPropertyNames() и Object.keys()?
Object.getOwnPropertyNames() возвращает перечислимые и не перечислимые свойства из объекта или массива.
Object.keys() возвращает перечислимые свойства из объекта или массива.- С помощью какой конструкции языка можно управлять потоком выполнения скрипта и отслеживать ошибки?
- Почему вызов a(); происходит успешно, а вызов b(); выдает ошибку?
Функция а() инициализируется на этапе загрузки скрипта, как бы "всплывает вверх" а функция б инициализируется, когда объявляется переменная b
- Что такое глобальные переменные? Как они создаются? Какие проблемы связаны с использованием глобальных переменных?
Глобальная переменная - переменная, которая доступна (видима) во всем документе, в отличии от локальной (ограничена рамками блока программного кода, внутри которого она определена)
Большинство JavaScript разработчиков избегает использования глобальных переменных. Одна из причин - возможный конфликт имен глобальных и локальных переменных. Так же код использующий глобальные переменные может быть тяжелее сопровождать и тестировать.
- Что такое замыкания (closure) в JavaScript?
Простыми словами это внутренняя функция, т.е. функция в функции.
Замыканием (closure) называют потому, что после выполнения родительской или внешней функции, код внутренней все еще "живет" в интерпретаторе, и его можно выполнить. Ошибок не возникнет даже если внутренняя функция (замыкание) будет использовать переменные из внешней функции. Например, эту особенность можно использовать для создания функций обработчиков событий:
- Напишите функцию принимающую строку с именем файла и возвращающую расширение (фрагмент после последней точки).
- Что такое prototype в javascript?
В общих чертах prototype - это свойство позволяющее добавлять уже существующим объектам свойства, также используется для эмуляции наследования классов в JavaScript. Подробный ответ написан здесь. Еще как вариант, можно упомянуть о Prototype.js. Это популярная библиотека добавляющая удобные ООП возможности в программы на JavaScript-е.
- Какие способы навешивания обработчиков событий вы знаете?
События можно добавлять тремя способами:
- htmlElement.onclick = function(event) { .... } - так можно добавить только один обработчик
- htmlElement.addEventListener("click", ...) - так можно навесить несколько обработчиков, сохраняет порядок обработчиков
- htmlElement.attachEvent("on"+имя_события, обработчик) - тоже можно навесить несколько, не сохраняет порядок обработчиков, нет доступа к элементу на котором сработало событие.
1. Есть некоторая строка (var str = "fgfggg";), что будет, если мы возьмем str?
Ответ
str вернет символ строки, который находится по нулевому индексу. Строка в js - immutable, то есть из нее можно прочитать символ, а вот записать нет.
2. Реализовать методы, которые в процессе выполнения строки (2).plus(3).minus(1) дали бы на выходе 4.
Ответ
Поскольку, мы работаем с числами, надо расширить прототип Number новыми методами.
Number.prototype.plus = function (value) {
return this + value;
}
Number.prototype.minus = function (value) {
return this - value;
}
Число два будет доступно через this в функции plus. Из нее мы возвращаем результат сложения числа, на которое указывает this и числа, переданного в качестве аргумента. Аналогично для minus.
3. Сейчас уже редко, но до сих еще спрашивают: «Почему плохо писать прямо в прототипы базовых типов?»
Ответ
Array.prototype.sort = function () {}
var t = ;
t.sort()
Ожидаемый результат - , а вернется undefined.
Мы рассчитываем, что стандартные методы сработают согласно документации, но какой-то разработчик можем переопределить метод, и он вернет совершенно неожиданный результат.
Именно поэтому библиотека prototype.js уступила jQuery.
4. Дана функция, она принимает в качестве аргументов строки "*", "1", "b", "1c", реализуйте ее так, что бы она вернула строку "1*b*1c"
Ответ
Ее можно решать прямо в лоб, перебирая в цикле все аргументы, но мы поступим умнее.
Function getStr() {
return .slice.call(arguments, 1).join(arguments)
}
5. Дано дерево, надо найти сумму всех вершин.
Ответ
Я решила задачу рекурсией, потом мы упростили решение, а затем переписали на очередь.
Рекурсия.
Var sum = 0;
function getSum(obj) {
sum += obj.valueNode;
if (obj.next != null) {
for (var i = 0; i < obj.next.length; i++) {
getSum(obj.next[i]);
}
}
return sum;
}
var tree1 = {
valueNode: 1,
next: [
{
valueNode: 3,
next: null
},
{
valueNode: 2,
next: null
}
]
}
var tree = {
valueNode: 3,
next: [{
valueNode: 1,
next: null
},
{
valueNode: 3,
next: null
},
{
valueNode: 2,
next: null
},
{
valueNode: 2,
next: [
{
valueNode: 1,
next: null
},
{
valueNode: 5,
next: null
}
]
}]
};
console.log(getSum(tree1));
sum = 0;
console.log(getSum(tree));
Очередь.
Function getSum(obj) {
var arr = ,
sum = 0,
current;
while(arr.length > 0) {
current = arr.shift();
sum += current.valueNode;
if (current.next != null) {
for (var i = 0; i < current.next.length; i++) {
arr.push(current.next[i]);
}
}
}
return sum;
}
var tree = {
valueNode: 3,
next: [{
valueNode: 1,
next: null
},
{
valueNode: 3,
next: null
},
{
valueNode: 2,
next: null
},
{
valueNode: 2,
next: [
{
valueNode: 1,
next: null
},
{
valueNode: 5,
next: null
}
]
}]
};
getSum(tree)
6. Можно ли из js менять значения в before, after?
Ответ
Нет, единственное что мы можем - это удалить класс, у которого указаны before или after, либо наоборот добавить.
Давайте, что-нибудь для разгрузки мозга, вопрос на верстку.
7. Вместить три блока 20X20px в ряд, в блок шириной 60px, при этом у блоков должны быть границы.
8. Как применяются скругленные углы для элементов и стили для текста(шрифт, тип шрифта, цветащте и тд)?
Ответ
Стилевые свойства применятся ко всем элементам с текстом, если у тегов не указаны стилевые правила. К примеру у ссылок указан цвет текста по умолчанию и он более приоритетный, чем определенный нами в body. Дело в том, что для многих свойств по умолчанию стоит значение inherit, то есть как у родителя. Получается поднимается вверх, пока не дойдет до body.
Для свойства border-radius, наоборот, применяется только к тегу, у которого мы хотим что бы били скругленные углы.
9. Что такое ресет стилей?
Ответ
Многим тегам стили прописаны по умолчанию, в процессе верстке нам приходится переопределять их. Что бы не делать это каждый раз, мы «скидываем» их «массово». Для этого заводим файл под стили, подключаем его первым или в первом стилевом файле, в самом верху указываем наши стили для базовых тегов.
К примеру. Мы часто используем список ul для верстки меню, для этого мы каждый раз вынуждены обнулять padding, margin и list-style-type. Можно один раз задать стили, и списки станут без внешней и внутренней границы, а так же без маркеров.
10. Требуется сверстать попап по центру, его размеры нам известны, но мы не хотим что бы он прокручивался вместе со страницей, причем по высоте может и не влезать в высоту экрана.
Ответ
body {
overflow: hidden;
}
.wrap {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow-y: auto;
background-color: rgba(230, 230, 230, .1);
}
.popup {
position: absolute;
width: 400px;
height: 300px;
right: 0;
left: 0;
top: 0;
bottom: 0;
margin: auto;
}
11. Нарисовать стилями полукруг.
Ответ
width: 100px;
height: 100px;
border-right: 1px solid #f00;
border-radius: 0 50% 50% 0;
12. Есть массив в котором лежат объекты с датами, отсортировать по датам.
Ответ
var arr = [{date: "10.01.2017"}, {date: "05.11.2016"}, {date: "21.13.2002"}];
arr.forEach(function(item) {
var arrDate = item.date.split("."),
date = new Date(Number(arrDate), Number(arrDate), Number(arrDate));
item.time = date.getTime();
});
arr.sort(function (a, b) {
if (a.time - b.time < 0) {
return false;
} else {
return true;
}
});
var res = arr.map(function (item) {
return {date: item.date};
});
console.log(res);
13. Есть несколько слов, определить состоят ли они из одних и тех же букв("кот", "ток", "окт")
Ответ
var arr = ["kot", "tok", "okt"],
arr1 = ["kot", "tok", "ott"];
function sameWords(arr) {
var word1, word2;
for (var i = 0; i < arr.length-1; i++) {
word1 = 0;
word2 = 0;
if (arr[i].length !== arr.length) {
return false;
} else {
for (var j = 0; j < arr[i].length; j++) {
word1 += arr[i][j].charCodeAt(0);
word2 += arr[j].charCodeAt(0);
}
if (word1 !== word2) {
return false;
}
}
}
return true;
}
console.log(sameWords(arr));
console.log(sameWords(arr1));
Ответ
Начну издалека, так как js-асинхронен, то в результате отслеживания завершения определенного когда в качестве аргументов передавались callback-функции, которые и вызывались по мере готовности. Цепочка ассинхронных методов росла, что приводило к Callback Hell, что затрудныло работу с кодом, отлаживание ошибок и им на смену пришли промисы.
Var promis = new Promise(function (resolve, reject) {
...
setTimeout(function () {
resolve(res);
}, 5000);
});
Несколько промисов можно объединить и получить разом ответ от них
var promisesImages = ;
for (let i = 0; i < count; i++) {
promisesImages.push(new Promise((resolveImg, rejectImg) => {
let img = new Image(),
startTime = Date.now();
img.src = this.imgUrl + "?" + Math.floor(Math.random() * 100000000);
img.onload = () => {
resolveImg(Date.now() - startTime);
};
img.onerror = rejectImg;
}));
}
Promise.all(promisesImages)
.then((timings) => {...})
17. И конечно вопрос на засыпку: «Каким образом можно обойтись без промисов?».
Ответ
По старинке, вводили переменную-счетчик и как-только наступало окончание очередного асинхронного действия, сравнивали переменную с общем количеством.
18. Еще вспомнился вопрос про обработку ошибок в промисах. У нас есть три запроса к серверу, один возвращает нам имя пользователя, второй его данные, а третий изображение для аватарки, мы для каждого запроса используем по промису, объединяя их в цепочку, что будет если в одном из запросов произойдет ошибка, довыполнится ли цепочка?
Ответ
Промисы все разрастаются и на смену Callback Hell приходит Promise Hell. Что же делать?
Ответ
function test() {
return new Promise(function (resolve) {
setTimeout (function () {
resolve(1);
})
})
}
async function test1() {
var res = await test();
console.log(res + 1);
}
Фактически выполнение test1 как бы «останавливается» до того момета пока мы не получим ответ от test. Я и раньше читала про эти методы, но особо не обращала внимание, а как-то в разговоре речь зашла о них, я удивилась: «Как так, выполнение останавливает, это же не понятно, что за функция, где она определена, когда callback - здесь все понятно, видно что произойдет в функции по завершению операции, ну или всегда можем поискать по имени, опять же, привычно про контекст». На что мне ответили, что у меня javascript головного мозга и я на столько привыкла к асинхронности, что синхронное выполнение мне кажется чем-то за гранью, а ведь в в пыхе, на которой я некогда программировала все синхронно, там даже если чтение из файла, пока не завершиться, дальше не продолжится.
(19)Вот еще один примерчик на асинхронность. Объяснить в какой последовательности выведутся цифры и почему так.
console.log(1); setTimeout(function() { console.log(2); }, 0) console.log(3);
Достаточно популярный, надо сказать. Вот мне он и достался в очередной раз. Уже отработано начала отвечать: «1, 3, 2. Так как хоть js и асинхронен, но внутри его есть очередь выполнения и setTimeout и setInterval, если им указан 0, помещают вызов функции в конец очереди.»
Тут надо сказать ребята зафейлились, заявив, что я ответила правильно, про 132, но не объяснила почему.
(20)Вообще вопросы на setTimeout и setInterval весьма актуальны.Меня спрашивали: «Какое минимальное время можно задать?»
Ответ
В каждом браузере есть свой минимум, если вы указываете меньше него, то все равно задержка будет не меньше минимуму. Иногда даже и больше указанного времени, так как задача попадает в очередь и время складывается из заданного плюс затраты в на выполнение на задач в очереди перед ней.
for (var i = 0; i < 10; i++) { setTimeout(function () { console.log(i); }, 100); }
21. Что будет выведено в консоль, как можно модифицировать пример что бы он возвращал правильный результат(назовите как можно больше способов)?
Ответ
Самый распространенный, обернуть в замыкание
For (var i = 0; i < 10; i++) {
(function (i) {
setTimeout(function () {
console.log(i);
}, 100);
})(i)
}
Не все обращали внимание, что в i можно передать не только контекст
For (var i = 0; i < 10; i++) {
setTimeout(function (i) {
console.log(i);
}.bind(this, i), 100);
}
Так же методам setInterval и setTimeout можно передать аргументы, которые будут прокинуты в качестве аргументов калбек-функции
for (var i = 0; i < 10; i++) {
setTimeout(function (i) {
console.log(i);
}, 100, i);
}
es6
For (let i = 0; i < 10; i++) {
setTimeout(function () {
console.log(i);
}, 100);
}
Одна из возможностей es6, в данном случае сработает несколько неожиданно, let не в блоке {}.
Давайте что-нибудь похардкорнее.
22. Надо написать функцию, которая вернет «hello world», но при этом в теле функции нельзя использовать ни цифры, ни буквы, а циклы, массивы, объекты можно, но без цифр.
Ответ
Увы, эти интересные люде не сказали мне как ее решать, поэтому, подумав дома, я могу только предположить.
Var zero = .length,
one = [{}].length,
two = [,].length,
seven = [,].length;
console.log(String.fromCharCode(Number(String(seven) + String(two))));
Так я получила букву H, но это изврат еще тот, осталось сделать оставшиеся 10 знаков…
(23) От них же. Числа от 1 до 100 лежат в массиве, они хаотично перемешанные, от туда изъяли одно число, надо найти, что это за число. алгоритм не должен превышать O(n^2) сложности.
Ответ
Пройти массив циклом и сложить все имеющиеся там цифры и вычесть из числа, полученного по формуле (n + 1) / (n / 2).
Мне пришло в голову более экзотическое решение. Детям и слабонервным лучше не смотреть.
Var sum = 101*50,
sumArr = eval(.join("+").replace("++", "+")),
res;
res = sum-sumArr;
Просто мне вспомнилось, что когда-то спрашивали: «Как быстрее всего найти сумму элементов массива?»
Ответ
eval(.join("+")
Вот на тот момент вспомнилось и не пришло ни чего лучше.
(24) Вот еще фейл-задача. Приведу дословно, те напишу как написали мне.
Function Book(name, author) {
this.name = name;
this.author = author;
return this;
}
function Foo(Book, "Учебник javascript", "Петр Сергеев")
Реализовать Foo
Ответ
Меня сбила эта строчка function Foo(Book, "Учебник javascript", "Петр Сергеев"). Только я вижу, что здесь что-то не так? Мне предложили решать через Object.create(), но я не согласна. Свойства и методы, записаные в саму функцию-конструктор, не будут «скопированы» Object.create.
Function Book(name, author) {
this.name = name;
this.author = author;
return this;
}
function Foo(Cclass, name, author) {
return Object.create(Cclass.prototype);
}
var book = Foo(Book, "js", "petr");
console.log(book.name); -> undefined
Конечно меня не взяли, а на последок посоветовали лучше учить теорию. Хнык-хнык.
В любом случае, я бы предпочла решать так.
Function Book(name, author) {
this.name = name;
this.author = author;
return this;
}
function Foo(Cclass, name, author) {
return Cclass.call({}, name, author);
}
var book = Foo(Book, "js", "petr");
console.log(book.name);
Хочу посоветовать чувакам лучше готовиться к собеседованиям.
Function isPalindrom1(str) {
if (str.toLowerCase().replace(/[^а-яА-ЯёЁ]/g, "") === str.toLowerCase().replace(/[^а-яА-ЯёЁ]/g,
"").split("").reverse().join("")) {
return true;
} else {
return false;
}
}
Красиво, просто, изящно.
Забавно, но где-то через год мне попался этот же вопрос. Я обрадовалась: «Свезло». Как оказалось, нет. Требовалось решить с помощью цикла, а регулярку можно было использовать только для одного символа. Собеседник мотивировал это тем, что replace с регуляркой по всей строке - слишком ресурсоемко.
Подумав дома, у меня получилось вот так:
function isPalindrom(str) {
var str = str.toLowerCase(),
lim = str.length - 1,
i = 0,
j = str.length - 1;
while (i 5, при вызове f(2)(3), тоже вернет 5
Ответ
function f(a, b) {
if (b !== undefined) {
return a + b;
} else {
return function (b) {
return a + b;
}
}
}
Хоть данный шаблон упоминается в книге Стефанова, на практике я ни разу не видела, что бы кто-то его использовал.
Более сложный вариант.
f(1)(2)(3)() -> 6, f(0)(3)(1)(5)() -> 8
Ответ
function f(arg) {
var value = arg;
return function (arg) {
if (arg !== undefined) {
return f(value + arg);
} else {
return value;
}
}
}
Реализовать функцию, которая возвращает результаты
Foo(1)(2)(3) -> 6
foo(1)(2)(3)(4) -> 10
foo(-1)(2)(3)(4)(7) -> 15
foo(1)(2)(3)...(n) вернет результатом сумму 1+2+3...+n
Самый сложный вариант, когда вызов этой конструкции не заканчивается пустыми скобками, а значит мы не имеем явного указателя на выход. Задача досталась не мне, в комментариях к статье мне любезно рассказали решение.
В итоге получилось
function foo(value) {
var acc = value;
function addNext(next) {
acc += next;
return addNext;
}
addNext.toString = addNext.valueOf = function() {
return acc;
}
return addNext;
}
29. На собесе на прошлую работу мне попался вопрос: "Что такое live/die"
Ответ
Где то из глубины сознания всплыло, что это аналог on/off, с помощью них можно навешивать/удалять обработчики на события их. Но более старые методы, по сравнению on/off.
В проекте я столкнулась с еще и с bind/unbind
Ответ
Мы не хотим находясь на одном сайте, получать данные с другого и как-то их обрабатывать. Что же делать? Может ajax, но у него есть ограничение по политике бозопасности. Надо что-то совпадали протокол, домен и порт, даже на поддомены мы не можем слать ajax-запросы.
Все же разработчики нашли некий лайфхак для крос-доменных запросов.
Если вы используете jquery, то всего-то надо указать в параметре «dataType» - «jsonp».
Мало кто знает, что лежит в основе данного запроса, реализация нативным js приблизительно такая
Var url = "http://mydomen.com/news.php",
script = document.createElement("script"),
callbackName = "jsonCallback" + Math.randome();
script.src = url + "?callback" + callbackName;
window = function(response){
console.log(response);
}
document.header.appendChild(script);
тег script начинает выкачивать скрипт, лежащий по адресу в атрибуте src, а после закачки, происходит выполнение. Поэтому мы создаем тег script. Случайным образом генерируем имя функции. Формируем урл к ресурсу, где в качестве параметра передается имя нашей новой функции.
В глобальную область, по ключу callbackName помещается функция, которая вызовется, при получение данных от ресурса, они станут доступны внутри через параметр.
На сервере ресурса сработает что-то в этом роде
echo $_REQUEST + "(" + json_encode($arDate) + ")";
В window попадет
window.jsonCallback0.90428777 -> function (response) {
console.log(response);
}
Так как теги с атрибутом src способы посылать только GET запросы, то jsonp не поддерживает POST
31. Заголовки CORS?
Ответ
Это альтернатива jsonp, в специальном заголовках перечисляются «доверенные» ресурсы, которые смогут получать данные от него, а если указать "*", то любые сайты, при обращение, станут получать данные.
Так же как и с jsonp доступны только GET запросы.
Когда я рассказывала про альтернативу jsonp интервьюер от этого вариант «отмахнулся», сказав, что не надежный. Я с ним не согласна. JSONP легче подменить, чем CORS-заголовки