-3
  1. Найти ошибки в коде

    Разработчик Василий торопился на встречу с коллегами, поэтому быстро написал программу. Код получился неидеальным. Помогите Василию исправить ошибки в коде:


const participants = ["Mary", "Kate"]

const sports = ["football", "hockey"]

function func(participants, sports) { /**

  • Подобно оператору new создает экземпляр объекта,
  • используя функцию-конструктор и параметры для нее

*/ function constructFrom(fnConstructor, params) { const res = {};

fnConstructor.bind(res).call(params);

Object.setPrototypeOf(res, fnConstructor);
return res;

}

/**

  • Создает пары вида [’вид спорта’, ’имя участника’],
  • где первому виду спорта соответствует последний участник

*/

function assignParicipants() { const participants = this.participants; const sports = this.sports; const orderIndexes = []; let i = sports.length;

while (i--) {
  orderIndexes.push(function () {
    return i;
  });
}

return orderIndexes.map(
  (getSportIndex, i) => [sports[i], participants[getSportIndex()]]
);

}

function Contest(participants, sports) { this.participants = participants; this.sports = sports; }

Contest.prototype.assignParicipants = assignParicipants;

const contest = constructFrom(Contest, participants, sports);

return contest.assignParicipants(); } console.log(func(participants, sports));

  1. И отправить исправленный вариант в качестве решения.
[["football","Kate"],["hockey","Mary"]]
Grundy
  • 81,538
Нуб
  • 3

1 Answers1

4

Первая строчка, которая бросается в глаза

fnConstructor.bind(res).call(params);

Что в ней происходит

  1. устанавливается контекст в res
  2. полученная функция вызывается с переданным контекстом params, который игнорируется, так как у результата функции bind нельзя сменить контекст.

Очевидно, здесь идет попытка вызвать функцию с переданными параметрами, передав ей в качестве контекста новый объект.

Для этого можно использовать метод .apply

fnConstructor.apply(res, params);

Стоит обратить внимание, что подразумевается возможность передать несколько параметров, поэтому params должен быть коллекцией, содержащей все переданные параметры.

Чтобы добиться этого нужно использовать синтаксис для rest parameters в определении функции

function constructFrom(fnConstructor, ...params) {

В этом случае первый параметр будет помещен в fnConstructor, а все оставшиеся собраны в params.

Далее идет установка прототипа для нового объекта. Стоит обратить внимание, что в качестве прототипа должен устанавливаться прототип функции конструктора, а не сам конструктор

Object.setPrototypeOf(res, fnConstructor.prototype);

Следующий недочет связан с замыканием переменной в цикле. Подробнее о решении этой проблемы можно посмотреть в ответе на вопрос Почему асинхронная функция внутри цикла выполняет последнюю итерацию много раз?

Например, можно сохранять значение счетчика на каждой итерации в переменную объявленную с помощью let.


Исправив указанные недочеты получаем ожидаемый ответ:

const participants = ["Mary", "Kate"]

const sports = ["football", "hockey"]

function func(participants, sports) { /**

  • Подобно оператору new создает экземпляр объекта,
  • используя функцию-конструктор и параметры для нее

*/ function constructFrom(fnConstructor, ...params) { const res = {};

fnConstructor.apply(res, params);

Object.setPrototypeOf(res, fnConstructor.prototype);
return res;

}

/**

  • Создает пары вида [’вид спорта’, ’имя участника’],
  • где первому виду спорта соответствует последний участник

*/

function assignParicipants() { const participants = this.participants; const sports = this.sports; const orderIndexes = []; let i = sports.length;

while (i--) {
  let ii = i;
  orderIndexes.push(function() {
    return ii;
  });
}

return orderIndexes.map(
  (getSportIndex, i) => [sports[i], participants[getSportIndex()]]
);

}

function Contest(participants, sports) { this.participants = participants; this.sports = sports; }

Contest.prototype.assignParicipants = assignParicipants;

const contest = constructFrom(Contest, participants, sports);

return contest.assignParicipants(); } console.log(func(participants, sports));

Grundy
  • 81,538