Выразительный JavaScript (Хавербеке) - страница 75

>      return dest;

>  }

>};

Сначала мы просто просим существо действовать, передавая ему объект >view, который знает про мир и текущее положение существа в мире (мы скоро зададим >View). Метод >act возвращает какое-либо действие.

Если тип действия не >“move”, оно игнорируется. Если >“move”, и если у него есть свойство >direction, ссылающееся на допустимое направление, и если клетка в этом направлении пустует (>null), мы назначаем клетке, где только что было существо, >null, и сохраняем существо в клетке назначения.

Заметьте, что >letAct заботится об игнорировании неправильных входных данных. Он не предполагает по умолчанию, что направление допустимо, или, что свойство типа имеет смысл. Такого рода защитное программирование в некоторых ситуациях имеет смысл. В основном это делается для проверки входных данных, приходящих от источников, которые вы не контролируете (ввод пользователя или чтение файла), но оно также полезно для изолирования подсистем друг от друга. В нашем случае его цель – учесть, что существа могут быть запрограммированы неаккуратно. Им не надо проверять, имеют ли их намерения смысл. Они просто запрашивают возможность действия, а мир сам решает, разрешать ли его.

Эти два метода не принадлежат к внешнему интерфейсу мирового объекта. Они являются деталями внутренней реализации. Некоторые языки предусматривают способы объявлять определённые методы и свойства «приватными», и выдавать ошибку при попытке их использования снаружи объекта. JavaScript не предусматривает такого, так что вам придётся полагаться на другие способы сообщить о том, что является частью интерфейса объекта. Иногда помогает использование схемы именования свойств для различения внутренних и внешних, например, с особыми приставками к именам внутренних, типа подчёркивания (>_). Это облегчит выявление случайного использования свойств, не являющихся частью интерфейса.

А пропущенная часть, тип >View, выглядит следующим образом:

>function View(world, vector) {

>  this.world = world;

>  this.vector = vector;

>}

>View.prototype.look = function(dir) {

>  var target = this.vector.plus(directions[dir]);

>  if (this.world.grid.isInside(target))

>    return charFromElement(this.world.grid.get(target));

>  else

>    return "#";

>};

>View.prototype.findAll = function(ch) {

>  var found = [];

>  for (var dir in directions)

>    if (this.look(dir) == ch)

>      found.push(dir);

>  return found;

>};

>View.prototype.find = function(ch) {

>  var found = this.findAll(ch);

>  if (found.length == 0) return null;

>  return randomElement(found);

>};

Метод >look вычисляет координаты, на которые мы пытаемся посмотреть. Если они находятся внутри сетки, то получает символ, соответствующий элементу, находящемуся там. Для координат снаружи сетки