» » » Марейн Хавербеке - Выразительный JavaScript


Авторские права

Марейн Хавербеке - Выразительный JavaScript

Здесь можно купить и скачать "Марейн Хавербеке - Выразительный JavaScript" в формате fb2, epub, txt, doc, pdf. Жанр: Программирование. Так же Вы можете читать ознакомительный отрывок из книги на сайте LibFox.Ru (ЛибФокс) или прочесть описание и ознакомиться с отзывами.
Марейн Хавербеке - Выразительный JavaScript
Рейтинг:
Название:
Выразительный JavaScript
Издательство:
неизвестно
Год:
неизвестен
ISBN:
978-1593275846
Вы автор?
Книга распространяется на условиях партнёрской программы.
Все авторские права соблюдены. Напишите нам, если Вы не согласны.

Как получить книгу?
Оплатили, но не знаете что делать дальше? Инструкция.

Описание книги "Выразительный JavaScript"

Описание и краткое содержание "Выразительный JavaScript" читать бесплатно онлайн.



В процессе чтения вы познакомитесь с основами программирования и, в частности, языка JavaScript, а также выполните несколько небольших проектов. Один из самых интересных проектов — создание своего языка программирования.






    // ... это наше личное свойство

  }

}

Объекты без прототипов

Но кроличья нора на этом не заканчивается. А если кто-то зарегистрировал имя hasOwnProperty в объекте map и назначил ему значение 42? Теперь вызов map.hasOwnProperty обращается к локальному свойству, в котором содержится номер, а не функция.

В таком случае прототипы только мешаются, и нам бы хотелось иметь объекты вообще без прототипов. Мы видели функцию Object.create, что позволяет создавать объект с заданным прототипом. Мы можем передать null для прототипа, чтобы создать свеженький объект без прототипа. Это то, что нам нужно для объектов типа map, где могут быть любые свойства.

var map = Object.create(null);

map["пицца"] = 0.069;

console.log("toString" in map);

// → false

console.log("пицца" in map);

// → true

Так-то лучше! Нам уже не нужна приблуда hasOwnProperty, потому что все свойства объекта заданы лично нами. Мы спокойно используем циклы for/in без оглядки на то, что люди творили с Object.prototype.

Полиморфизм

Когда вы вызываете функцию String, преобразующую значение в строку, для объекта, он вызовет метод toString, чтобы создать осмысленную строчку. Я упомянул, что некоторые стандартные прототипы объявляют свои версии toString для создания строк, более полезных, чем просто "[object Object]".

Это простой пример мощной идеи. Когда кусок кода написан так, чтобы работать с объектами через определённый интерфейс – в нашем случае через метод toString – любой объект, поддерживающий этот интерфейс, можно подключить к коду, и всё будет просто работать.

Такая техника называется полиморфизм, хотя никто и не меняет своей формы. Полиморфный код может работать со значениями самых разных форм, пока они поддерживают одинаковый интерфейс.

Форматируем таблицу

Давайте рассмотрим пример, чтобы понять, как выглядит полиморфизм, да и вообще объектно-ориентированное программирование. Проект следующий: мы напишем программу, которая получает массив массивов из ячеек таблицы, и строит строку, содержащую красиво отформатированную таблицу. То есть, колонки и ряды выровнены. Типа вот этого:

name         height country

------------ ------ -------------

Kilimanjaro    5895 Tanzania

Everest        8848 Nepal

Mount Fuji     3776 Japan

Mont Blanc     4808 Italy/France

Vaalserberg     323 Netherlands

Denali         6168 United States

Popocatepetl   5465 Mexico

Работать она будет так: основная функция будет спрашивать каждую ячейку, какой она ширины и высоты, и потом использует эту информацию для определения ширины колонок и высоты рядов. Затем она попросит ячейки нарисовать себя, и соберёт результаты в одну строку.

Программа будет общаться с объектами ячеек через хорошо определённый интерфейс. Типы ячеек не будут заданы жёстко. Мы сможем добавлять новые стили ячеек – к примеру, подчёркнутые ячейки у заголовка. И если они будут поддерживать наш интерфейс, они просто заработают, без изменений в программе. Интерфейс:

• minHeight() возвращает число, показывающее минимальную высоту, которую требует ячейка (выраженную в строчках)

• minWidth() возвращает число, показывающее минимальную ширину, которую требует ячейка (выраженную в символах)

• draw(width, height) возвращает массив длины height, содержащий наборы строк, каждая из которых шириной в width символов. Это содержимое ячейки.

Я буду использовать функции высшего порядка, поскольку они здесь очень уместны.

Первая часть программы вычисляет массивы минимальных ширин колонок и высот строк для матрицы ячеек. Переменная rows будет содержать массив массивов, где каждый внутренний массив – это строка ячеек.

function rowHeights(rows) {

  return rows.map(function(row) {

    return row.reduce(function(max, cell) {

      return Math.max(max, cell.minHeight());

    }, 0);

  });

}


function colWidths(rows) {

  return rows[0].map(function(_, i) {

    return rows.reduce(function(max, row) {

      return Math.max(max, row[i].minWidth());

    }, 0);

  });

}

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

Функция rowHeights не должна вызвать затруднений. Она использует reduce для подсчёта максимальной высоты массива ячеек, и заворачивает это в map, чтобы пройти все строки в массиве rows.

Ситуация с colWidths посложнее, потому что внешний массив – это массив строк, а не столбцов. Я забыл упомянуть, что map (как и forEach, filter и похожие методы массивов) передаёт в заданную функцию второй аргумент – индекс текущего элемента. Проходя при помощи map элементы первой строки и используя только второй аргумент функции, colWidths строит массив с одним элементом для каждого индекса столбца. Вызов reduce проходит по внешнему массиву rows для каждого индекса, и выбирает ширину широчайшей ячейки в этом индексе.

Код для вывода таблицы:

function drawTable(rows) {

  var heights = rowHeights(rows);

  var widths = colWidths(rows);


  function drawLine(blocks, lineNo) {

    return blocks.map(function(block) {

      return block[lineNo];

    }).join(" ");

  }


  function drawRow(row, rowNum) {

    var blocks = row.map(function(cell, colNum) {

      return cell.draw(widths[colNum], heights[rowNum]);

    });

    return blocks[0].map(function(_, lineNo) {

      return drawLine(blocks, lineNo);

    }).join("\n");

  }


  return rows.map(drawRow).join("\n");

}

Функция drawTable использует внутреннюю функцию drawRow для рисования всех строк, соединяя их через символы новой строки.

Функция drawRow сперва превращает объекты ячеек строки в блоки, которые являются массивами строк, представляющими содержимое ячеек, разделённые линиями. Одна ячейка, содержащая число 3776, может быть представлена массивом из одного элемента ["3776"], а подчёркнутая ячейка может занять две строки и выглядеть как массив ["name", "----"].

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

Функция drawLine выцепляет строки, которые должны располагаться рядом друг с другом, из массива блоков и соединяет их через пробел, чтобы создать промежуток в один символ между столбцами таблицы.

Давайте напишем конструктор для ячеек, содержащих текст, который предоставляет интерфейс для ячеек. Он разбивает строчку в массив строк при помощи метода split, который режет строчку каждый раз, когда в ней встречается его аргумент, и возвращает массив полученных кусочков. Метод minWidth находит максимальную ширину строки в массиве.

function repeat(string, times) {

  var result = "";

  for (var i = 0; i < times; i++)

    result += string;

  return result;

}


function TextCell(text) {

  this.text = text.split("\n");

}

TextCell.prototype.minWidth = function() {

  return this.text.reduce(function(width, line) {

    return Math.max(width, line.length);

  }, 0);

};

TextCell.prototype.minHeight = function() {

  return this.text.length;

};

TextCell.prototype.draw = function(width, height) {

  var result = [];

  for (var i = 0; i < height; i++) {

    var line = this.text[i] || "";

    result.push(line + repeat(" ", width - line.length));

  }

  return result;

};

В коде используется вспомогательная функция repeat, которая возвращает переданную первым аргументом строку, повторённую переданное вторым аргументом количество раз. Метод draw использует её для создания отступов в ячейках, чтобы они все были необходимой длины.

Давайте нарисуем для опыта шахматную доску 5×5.

var rows = [];

for (var i = 0; i < 5; i++) {

   var row = [];

   for (var j = 0; j < 5; j++) {

     if ((j + i) % 2 == 0)

       row.push(new TextCell("##"));

     else

       row.push(new TextCell("  "));

   }

   rows.push(row);

}

console.log(drawTable(rows));

// → ##    ##    ##

//      ##    ##

//   ##    ##    ##


На Facebook В Твиттере В Instagram В Одноклассниках Мы Вконтакте
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!

Похожие книги на "Выразительный JavaScript"

Книги похожие на "Выразительный JavaScript" читать онлайн или скачать бесплатно полные версии.


Понравилась книга? Оставьте Ваш комментарий, поделитесь впечатлениями или расскажите друзьям

Все книги автора Марейн Хавербеке

Марейн Хавербеке - все книги автора в одном месте на сайте онлайн библиотеки LibFox.

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Отзывы о "Марейн Хавербеке - Выразительный JavaScript"

Отзывы читателей о книге "Выразительный JavaScript", комментарии и мнения людей о произведении.

А что Вы думаете о книге? Оставьте Ваш отзыв.