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

Исходные данные для таблицы гор, которую мы строим, содержатся в переменной >MOUNTAINS, их можно скачать тут.

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

>function UnderlinedCell(inner) {

>  this.inner = inner;

>};

>UnderlinedCell.prototype.minWidth = function() {

>  return this.inner.minWidth();

>};

>UnderlinedCell.prototype.minHeight = function() {

>  return this.inner.minHeight() + 1;

>};

>UnderlinedCell.prototype.draw = function(width, height) {

>  return this.inner.draw(width, height - 1)

>    .concat([repeat("-", width)]);

>};

Подчёркнутая ячейка содержит другую ячейку. Она возвращает такие же размеры, как и у ячейки >inner (через вызовы её методов >minWidth и >minHeight), но добавляет единичку к высоте из-за места, занятого чёрточками.

Рисовать её просто – мы берём содержимое ячейки >inner и добавляем одну строку, заполненную чёрточками.

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

>function dataTable(data) {

>  var keys = Object.keys(data[0]);

>  var headers = keys.map(function(name) {

>    return new UnderlinedCell(new TextCell(name));

>  });

>  var body = data.map(function(row) {

>    return keys.map(function(name) {

>      return new TextCell(String(row[name]));

>    });

>  });

>  return [headers].concat(body);

>}


>console.log(drawTable(dataTable(MOUNTAINS)));

>// → name         height country

>//   ------------ ------ -------------

>//   Kilimanjaro  5895   Tanzania

>//   … и так далее

Стандартная функция >Object.keys возвращает массив имён свойств объекта. Верхняя строка таблицы состоит из подчёркнутых ячеек с заголовками столбцов. Всё что ниже – значения из набора данных – имеет вид обычных ячеек. Мы извлекаем эти данные проходом функции >map по массиву >keys, чтобы гарантировать одинаковый порядок ячеек в каждой из строк.

Итоговая таблица напоминает таблицу из примера, только вот числа не выровнены по правому краю. Мы займёмся этим чуть позже.

Геттеры и сеттеры

При создании интерфейса можно ввести свойства, не являющиеся методами. Мы могли бы определить >minHeight и >minWidth как переменные для хранения чисел. Но это потребовало бы от нас написать код вычисления их значений в конструкторе, что плохо, поскольку эти операции не связаны напрямую с конструированием объекта. Это может аукнуться, когда, например, внутренняя ячейка подчёркнутой ячейки изменяется – в этот момент размер подчеркивания тоже должен измениться.

Эти соображения привели к тому, что свойства, не являющиеся методами, многие не включают в интерфейс. Вместо прямого доступа к свойствам-значениям, используются методы типа