Разбор Luxoft JavaScript quiz

Разбор Luxoft JavaScript quiz

Maksym Pohribniak
luxoft JS Quiz

Совсем недавно компания Luxoft проводила JS Quiz, ссылка на который висела на главной странице dou.ua. В котором можно было выиграть футболку или повербанк. К слову, я выиграл футболку, так как у меня было 13 правильных ответов (из 15 возможных). Не хватило одного балла для повербанка. (один вопрос я неправильно решил из-за невнимательности (№1), а второй спорный (№8)).

Так, как тест уже закончился и по ссылке висят ответы – я хочу разобрать некоторые вопросы из него:

Вопрос #5

Which of the results of the following won't have a number type?
Какой из следующих результатов не будет иметь числовой тип?

Варианты ответов:

a) 77 + '77'
Неявное преобразование в строку будет вызвано бинарным оператором +, кода один из операндов является строкой.

b) Number('Not a ')
Вернет NaN, а typeof NaNnumber.

c) '11' * 1
Численное преобразование происходит в математических функциях и выражениях. Например, когда операция применяется не к числу как в нашем примере. (кроме +).

d) parseFloat(‘123.45’)
Может вернуть значение Infinity, NaN или число и все они типа число.


✅ Правильный ответ - а (77 + '77')


Вопрос #6

What is the length of the array?
Какова длина массива?

[...[...'...']]

Варианты ответов:

a) 1

b) 2

c) 3

Для лучшего понимания перепишем данный код на более читабельный:

const str = '...';
const innerArr = [...str];
// spread оператор на строке работает так же, как использование .split('').
// innerArr будет представлять собой следующий массив [".", ".", "."]
const outerArr = [...innerArr];
// используем spread syntax для создания нового массива на основе существующего


✅ Правильный ответ - c (3)


Вопрос #7

What will be the output?
Какой будет результат?

let x, { x: y = 1 } = { x };
console.log(y);

Варианты ответов:

a) undefined

b) 1

c) { x }

Для лучшего понимания перепишем данный код на более читабельный:

let x; // объявляем переменную х
let { x: y = 1 } = { "x": x };
// с помощью оператора деструктуризации достаем ключ х как переменную y из объекта { "x": undefined }
// с дефолтныйм значением 1
// так как х === undefined, проставляется дефолтное значение
console.log(y); // 1


✅ Правильный ответ - b (1)


Вопрос #9

It's time for chaining assignments on objects. What will be the output?
Какой будет результат кода?

let foo = { n: 1 };
let bar = foo;
foo.x = foo = { n: 2 };

console.log(foo.x);
console.log(foo);
console.log(bar);

К сожалению варианты ответов именно к этому вопросу я не записал потому будут мои:

а) undefined, { n: 2 }, { n: 1, x: { n: 2 } }

b) {n: 2}, {n: 2, x: {n: 2}}, {n: 1}

c) undefined, { n: 2 }, { n: 1, x: undefined }


Для правильного решения данного задания нам нужно понимать 2 вещи:

  • объекты передаются по ссылке
let a = {test: 1};
let b = a; // b и a теперь ссылаются на одну и туже область памяти
a = 2; // a больше не ссылается на объект {test: 1}
console.log(b) // {test: 1} ссылается на объект который изначально был а
  •  операторы присваивания являются право-ассоциативными
a = b = 5; // a и b будут равны 5

 Это происходит, потому что оператор присваивания возвращает тот результат, который присваивает. Сначала b становится равным 5, затем a принимает значение b.

Возвращаемся к нашему примеру:

let foo = { n: 1 }; // создали объект
let bar = foo; // передали ссылку на выше созданный объект
foo.x = foo = { n: 2 };
// так, как операторы присваивания являются право-ассоциативными
// исполнения правой части кода (foo = { n: 2 })
// переменная foo принимает ссылку на совершенно новый объект
// при этом левая часть (foo.x) все еще ссылается на старый объект { n: 1 }
// на который так же ссылается bar
// и в foo.x(bar) мы записываем результат выполнения (foo = { n: 2 }) – { n: 2 }
// после выполнения этой строки в foo у нас лежит новый объкт
// а в bar.x мы записали ссылку на новый foo
console.log(foo.x); // undefined
console.log(foo); // {n: 2}
console.log(bar); // {n: 1, x: {{n: 2}}}


✅ Правильный ответ - а) undefined, { n: 2 }, { n: 1, x: { n: 2 } }


Вопрос #10

One of the common questions about 'setTimeout.' What will be the output?
Типичный вопрос про таймауты. Какой будет результат кода?

for ( var i = 0 ; i < 3 ; i++) {
setTimeout(() => console.log(i));
}

Варианты ответов:

a) 1 2 3

b) 0 1 2

c) 3 3 3


Этот вопрос направлен на понимание таких механизмов JS, как замыкания, области видимости и функция setTimeout. И его ответ стыдно уже не знать так как его спрашивают везде и только ленивый не писал разбор на него.

Функция setTimeout создаёт функцию (замыкание), у которой есть доступ к внешней по области видимости и переменной  i. Функция выполняется (aсинхронный setTimeout выполняется после того как выполнится весь синхронный код, то есть на момент выполнения функции в setTimeout цыкл уже завершил свою работу) и выводит значение i, которое, после окончания выполнения цикла равняется 3.


✅ Правильный ответ - c (3 3 3)


Вопрос #11

Let's continue with setInterval + Promise. What will be the output?
setInterval + Promise. Какой будет результат кода?

(() => {
console.log('START');

const interval = setInterval(() => {
console.log('setInterval');
clearInterval(interval);
}, 0);

Promise.resolve().then(() => console.log('promise'));

console.log('END');
})();

Варианты ответов:

a) START END promise setInterval

b) START setInterval promise END

c) START END setInterval promise

Разбор этого же вопроса я уже описывал более детально здесь.


✅ Правильный ответ - a) START END promise setInterval


Вопрос #12

Ok, and what we will get after running this code?
Какой будет результат кода?

((x, func = () => x) => {
var x;
var y = x;
x = 2
return [x, y, func()];
})(1);

Варианты ответов:

a) [2,1,2]

b) [2,1,1]

c) [2, undefined,1]

Мы вызываем анонимную функцию и сразу же ей передаем один аргумент 1.
Параметр x внутри анонимной функции будет единицей.

Функцию func мы не передаем, потому используется её значение по умолчанию.
В параметрах по умолчанию можно использовать значения предыдущих (расположенных левее в списке) параметров.

Переменная х доступна для видимости из функции func и тоже 1.

Далее мы объявляем переменную x c помощью var. Переменные var считаются объявленными с самого начала исполнения функции вне зависимости от того, в каком месте функции реально находятся их объявления (при условии, что они не находятся во вложенной функции). Поэтому в данном случае var x ничего не делает. х у нас остается 1. Далее мы копируем значение x в переменную y, а в следующей строке изменяем значение x (y при этом не меняется т. к. значение 2 – примитив).
И возвращаем мы массив элементов [x, y, func()], где:
x = 2;
y = 1;
func() = 1;
так как func замкнулся на значении x=1 при инициализации дефолтных параметров.


✅ Правильный ответ - b) [2,1,1]


Вопрос #13

And, for 'arguments,' what will we get here:
И что касается «аргументов», что мы получим здесь:

function func1(x, y) {
arguments[0] = y;
return x;
}

function func2(x, y) {
return [ arguments[1], func1(x, y)];
}

func2(1, 2);

Варианты ответов:

a) [1,2]

b) [2,1]

c) [2,2]

Аргументы будут ссылаться на последние значения объекта arguments, при считывании значений аргументов будут считаны последние данные из arguments, а при изменении значений формальных аргументов будет обновлен и объект arguments.

То есть запись arguments[0] = y; эквивалента записи x = y;


✅ Правильный ответ - c) [2, 2]


Вопрос #14

Now the arrow function. What will we get after running this code:
Теперь стрелочные функции. Что мы получим после запуска этого кода:

let f1 = () => {};
f1();

let f2 = () => {
this.a = 1;
};

new f2();

let f3 = () => arguments;
f3('a')

Варианты ответов:

a) {} TypeError ReferenceError

b) undefined { ‘a’: 1 } [‘a’]

c) undefined TypeError ReferenceError

Здесь нужно знать как работают стлелочные функции и их ограничения, они:

  • не имееют собственного объекта arguments
  •  не могут быть использованы как конструктор и вызовут ошибку при использовании с new
  • стрелочные функции не могут быть использованы как генераторы

Запись let f1 = () => {}; Всего лишь создает функцию с пустым телом, а не возвращает объект как может показаться (из-pа неявного return);

Чтобы вернулся объект нужна дополнительная магия в виде скобок:

let f1 = () => ({});


✅ Правильный ответ - c) undefined TypeError ReferenceError


Если вам показался полезным и интересным мой разбор с объяснениями, присылайте мне в личку тесты или вопросы интересующие вас.
По ним я сделаю еще один разбор.

Спасибо за внимание!


Report Page