Закрытие, возвращающее массив / объект, раскрывает свой лексический контекст: лучший способ решения в JavaScript? - PullRequest
0 голосов
/ 14 декабря 2018

Полагаю, это может быть дубликат, но я пока не смог найти объяснения.

Вот мой пример кода:

const makeCalendar = () => {
  const calendar = {};

  calendar.xmas = ['December', 25];
  calendar.newYear = ['January', 1];

  return (day) => calendar[day];
}

calendar = makeCalendar();
const xmasArray = calendar('xmas');

console.log(calendar('xmas')); // [ 'December', 25 ]

xmasArray[1]++;

console.log(calendar('xmas')); // [ 'December', 26 ]

Поскольку элементы xmasArray являются изменяемыми, я могу изменять переменные внутри области действия makeCalendar() и, таким образом, повреждать замыкание, которое оно возвращает.Единственный способ решить эту проблему - вернуть анонимный массив [...calendar[day]] (вместо calendar[day]), который затем блокирует доступ внутри makeCalendar().

Мои вопросы: верно ли это?способ справиться с этой проблемой?Есть ли лучшие способы?Возможно, я не правильно понимаю, что происходит ...

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Один из вариантов - использовать Object.freeze, чтобы запретить присваивание любым элементам в массиве:

const makeCalendar = () => {
  const calendar = {
    xmas: ['December', 25],
    newYear: ['January', 1]
  };
  Object.values(calendar).forEach(arr => Object.freeze(arr));
  return (day) => calendar[day];
}

calendar = makeCalendar();
const xmasArray = calendar('xmas');

console.log(calendar('xmas'));

xmasArray[1]++;

console.log(calendar('xmas'));

Обратите внимание, что такая попытка назначения вызовет ошибку в строгом режиме:

Uncaught TypeError: Cannot assign to read only property '1' of object '[object Array]
0 голосов
/ 14 декабря 2018
const makeCalendar = () => {
  const calendar = {};

  calendar.xmas = ['December', 25];
  calendar.newYear = ['January', 1];

  return (day) => JSON.parse(JSON.stringify(calendar))[day];
}

Не лучший вариант, если объект календаря становится значительно большим, но все еще работает.В этом случае, в частности, даже JSON.parse(JSON.stringify(calendar[day])) сработает.

Хитрость заключается в том, что выполнение синтаксического анализа и stringify создаст новую копию исходного объекта, поэтому на исходную копию это никак не повлияет.Конечно, вы можете использовать другие способы клонирования объекта, вы можете найти больше информации здесь: Какой самый эффективный способ глубокого клонирования объекта в JavaScript?

fiddle: http://jsfiddle.net/briosheje/317hg6fb/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...