В моей недавней статье « String
базовых объектов JavaScript» было показано, как представить новые свойства и методы базовых объектов JavaScript Array
, Boolean
, Date
, Math
, Number
и String
. Я следовал традиции других статей и постов в блогах, в том числе перечисленных ниже, которые показывают, как расширить эти основные объекты новыми возможностями:
- Расширьте Math.round, Math.ceil и Math.floor, чтобы обеспечить точность
- Расширение объектов и классов JavaScript
- Расширение строкового объекта JavaScript
- Расширение объекта JavaScript Date с помощью пользовательских методов
- Массив JavaScript содержит
Непосредственно при добавлении свойства основного объекта или его прототип, является спорным. В своем блоге, посвященном расширению JavaScript , Angus Croll рассматривает несколько проблем с этим подходом. Например, в будущих версиях браузера может быть реализовано эффективное свойство или метод, который перекрывается менее эффективным пользовательским свойством / методом. Прочитайте сообщение в блоге Croll для получения дополнительной информации по этой и другим проблемам
Поскольку расширение основных объектов является мощным и элегантным, должен быть способ использовать эту функцию, избегая ее проблем. К счастью, есть способ выполнить эту задачу, используя шаблон проектирования адаптера , который также известен как шаблон оболочки. В этой статье я представляю новую версию моей библиотеки, которая использует обертку для дополнения различных основных объектов, фактически не увеличивая их.
Изучение новой библиотеки дополнения базового объекта
Моя новая библиотека расширения основных объектов пытается минимизировать ее влияние на глобальное пространство имен, используя шаблон модуля JavaScript , который помещает весь код библиотеки в анонимное закрытие. В настоящее время эта библиотека экспортирует _Date
и _Math
которые обертываются вокруг Date
и Math
, и для доступа к ней используется ca_tutortutor_AJSCOLib
глобальной переменной ca_tutortutor_AJSCOLib
.
О ca_tutortutor_AJSCOLib
Глобальная переменная ca_tutortutor_AJSCOLib
обеспечивает доступ к библиотеке дополнения. Чтобы свести к минимуму вероятность конфликта имен с другой глобальной переменной, я AJSCOLib
префикс AJSCOLib
к своему обратному доменному имени в Интернете.
В листинге 1 представлено содержимое моей библиотеки, которая хранится в ajscolib.js
сценария ajscolib.js
.
var ca_tutortutor_AJSCOLib = (Функция () { var my = {}; var _Date_ = Date; Функция _Date (год, месяц, дата, часы, минуты, секунды, мс) { если (год === не определено) this.instance = new _Date_ (); еще если (месяц === не определено) this.instance = new _Date_ (year); еще если (часов === не определено) this.instance = new _Date_ (год, месяц, дата); еще this.instance = new _Date_ (год, месяц, дата, часы, минуты, секунды, Миз); this.copy = Функция () { вернуть новый _Date_ (this.instance.getTime ()); }; this.getDate = Функция () { вернуть this.instance.getDate (); }; this.getDay = Функция () { вернуть this.instance.getDay (); }; this.getFullYear = Функция () { вернуть this.instance.getFullYear (); }; this.getHours = Функция () { вернуть this.instance.getHours (); }; this.getMilliseconds = Функция () { вернуть this.instance.getMilliseconds (); }; this.getMinutes = Функция () { вернуть this.instance.getMinutes (); }; this.getMonth = Функция () { вернуть this.instance.getMonth (); }; this.getSeconds = Функция () { вернуть this.instance.getSeconds (); }; this.getTime = Функция () { вернуть this.instance.getTime (); }; this.getTimezoneOffset = Функция () { return this.instance.getTimezoneOffset (); }; this.getUTCDate = Функция () { вернуть this.instance.getUTCDate (); }; this.getUTCDay = Функция () { вернуть this.instance.getUTCDay (); }; this.getUTCFullYear = Функция () { вернуть this.instance.getUTCFullYear (); }; this.getUTCHours = Функция () { вернуть this.instance.getUTCHours (); }; this.getUTCMilliseconds = Функция () { вернуть this.instance.getUTCMilliseconds (); }; this.getUTCMinutes = Функция () { вернуть this.instance.getUTCMinutes (); }; this.getUTCMonth = Функция () { вернуть this.instance.getUTCMonth (); }; this.getUTCSeconds = Функция () { вернуть this.instance.getUTCSeconds (); }; this.getYear = Функция () { вернуть this.instance.getYear (); }; this.isLeap = Функция () { var year = this.instance.getFullYear (); доход (год% 400 == 0) || (год% 4 == 0 && год% 100! = 0); }; _Date.isLeap = Функция (дата) { if (date instanceof _Date) date = date.instance; var year = date.getFullYear (); доход (год% 400 == 0) || (год% 4 == 0 && год% 100! = 0); }; this.lastDay = Функция () { вернуть новую _Date_ (this.instance.getFullYear (), this.instance.getMonth () + 1, 0) .getDate (); }; _Date.monthNames = ["Январь", "Февраль", "Март", "Апрель", "Май", «Июнь», «июль», «август», «сентябрь», «октябрь», "Ноябрь декабрь"]; _Date.parse = Функция (дата) { if (date instanceof _Date) date = date.instance; return _Date_.parse (date); }; this.setDate = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setDate (дата); }; this.setFullYear = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setFullYear (дата); }; this.setHours = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setHours (дата); }; this.setMilliseconds = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setMilliseconds (дата); }; this.setMinutes = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setMinutes (дата); }; this.setMonth = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setMonth (дата); }; this.setSeconds = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setSeconds (дата); }; this.setTime = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setTime (дата); }; this.setUTCDate = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setUTCDate (дата); }; this.setUTCFullYear = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setUTCFullYear (дата); }; this.setUTCHours = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setUTCHours (дата); }; this.setUTCMilliseconds = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setUTCMilliseconds (дата); }; this.setUTCMinutes = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setUTCMinutes (дата); }; this.setUTCMonth = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setUTCMonth (дата); }; this.setUTCSeconds = Функция (дата) { if (date instanceof _Date) date = date.instance; this.instance.setUTCSeconds (дата); }; this.toDateString = Функция () { вернуть this.instance.toDateString (); }; this.toISOString = Функция () { вернуть this.instance.toISOString (); }; this.toJSON = Функция () { вернуть this.instance.toJSON (); }; this.toLocaleDateString = Функция () { вернуть this.instance.toLocaleDateString (); }; this.toLocaleTimeString = Функция () { вернуть this.instance.toLocaleTimeString (); }; this.toString = Функция () { вернуть this.instance.toString (); }; this.toTimeString = Функция () { вернуть this.instance.toTimeString (); }; this.toUTCString = Функция () { вернуть this.instance.toUTCString (); }; _Date.UTC = Функция (дата) { if (date instanceof _Date) date = date.instance; return _Date_.UTC (date); }; this.valueOf = Функция () { вернуть this.instance.valueOf (); }; } my._Date = _Date; var _Math = {}; var props = Object.getOwnPropertyNames (Math); props.forEach (функция (клавиша) { if (Math [ключ]) _Math [ключ] = математика [ключ]; }); если (! _Math.GOLDEN_RATIO) _Math.GOLDEN_RATIO = 1.61803398874; if (! _Math.rnd || _Math.rnd.length! = 1) _Math.rnd = функция (предел) { if (typeof limit! = "number") бросить "незаконный аргумент:" + предел; return Math.random () * limit | 0; }; if (! _Math.rndRange || _Math.rndRange.length! = 2) _Math.rndRange = функция (мин, макс) { if (typeof min! = "number") бросить "незаконный аргумент": + мин; if (typeof max! = "number") бросить "незаконный аргумент": + max; return Math.floor (Math.random () * (max - min + 1)) + min; }; if (! _Math.toDegrees || _Math.toDegrees.length! = 1) _Math.toDegrees = Функция (радианы) { if (typeof радианы! = "число") киньте «незаконный аргумент»: + радианы; обратные радианы * (180 / Math.PI); }; if (! _Math.toRadians || _Math.toRadians.length! = 1) _Math.toRadians = Функция (в градусах) { if (typeof градусов! = "число") бросить "незаконный аргумент:" + градусы; обратные градусы * (Math.PI / 180); }; if (! _Math.trunc || _Math.trunc.length! = 1) _Math.trunc = Функция (п) { if (typeof n! = "number") бросить "недопустимый аргумент": + n; возврат (n> = 0)? Math.floor (n): -Math.floor (-n); }; my._Math = _Math; вернуть мой; } ());
Листинг 1: Эта автономная библиотека дополнений может быть расширена для поддержки всех основных объектов
Все переменные и функции, объявленные в анонимном закрытии, являются локальными для этого замыкания. Для доступа извне замыкания необходимо экспортировать переменную или функцию. Чтобы экспортировать переменную или функцию, просто добавьте ее к объекту и верните этот объект из замыкания. В листинге 1 объект известен как my
и ему назначена _Date
функцию _Date
и _Math
объект _Math
.
После объявления переменной my
, которая инициализируется пустым объектом, в листинге 1 объявляется переменная _Date_
, которая ссылается на основной объект Date
. Где бы мне ни понадобился доступ к Date
из библиотеки, я _Date_
к _Date_
вместо Date
. Я объясню причину этого соглашения позже в этой статье.
В листинге 1 теперь объявляется конструктор _Date
для _Date
объектов- _Date
. Этот конструктор объявляет те же параметры year
, month
, date
, hours
, minutes
, seconds
и ms
что и базовый объект Date
. Эти параметры опрашиваются, чтобы определить, какой вариант конструктора Date
вызывать:
-
_Date()
вызываетDate()
для инициализации объектаDate
текущей датой. Этот сценарий определяетсяyear
тестирования дляundefined
. -
_Date(year)
вызываетDate(milliseconds)
илиDate(dateString)
для инициализации объектаDate
указанным числом миллисекунд или строкой даты — я оставляю егоDate
для обработки любого случая. Этот сценарий обнаруживается тестированиемmonth
наundefined
. -
_Date(year, month, date)
вызывает_Date(year, month, date)
для инициализации объектаDate
указанным годом, месяцем и днем месяца (дата). Этот сценарий обнаруживается поhour
тестирования наundefined
. -
_Date(year, month, day, hours, minutes, seconds, milliseconds)
вызываетDate(year, month, day, hours, minutes, seconds, milliseconds)
для инициализации объектаDate
датой, описанной отдельными компонентами. Этот сценарий по умолчанию.
Независимо от того, какой вариант конструктора (вызов конструктора со всеми или меньшим числом аргументов) вызывается, возвращаемый результат сохраняется в _Date
instance
_Date
. Вы никогда не должны обращаться к instance
напрямую, потому что вам может потребоваться переименовать это свойство, если Date
введет свойство instance
в будущем. Отсутствие доступа к instance
за пределами библиотеки уменьшает обслуживание кода.
На данный момент в листинге 1 регистрируются новые методы copy()
, isLeap()
и lastDay()
, а также новое свойство _Date
с _Date
. Он также регистрирует методы Date
. Первые методы дополняют Date
новой функциональностью, связанной с _Date
вместо Date
, и описаны ниже. Последние методы используют instance
для доступа к ранее сохраненному экземпляру Date
, обычно для вызова своих аналогов Date
:
-
copy()
создает копию экземпляра объектаDate
который вызывает этот метод. Другими словами, он клонирует экземплярDate
. Пример:var d = new Date(); var d2 = d.copy();
var d = new Date(); var d2 = d.copy();
-
isLeap()
возвращает true, когда часть года экземпляра вызывающего объектаDate
представляет високосный год; в противном случае ложное возвращение. Пример:var d = new Date(); alert(d.isLeap());
var d = new Date(); alert(d.isLeap());
-
isLeap(date)
возвращает true, когда годовая частьdate
представляет високосный год; в противном случае ложное возвращение. Пример:alert(Date.isLeap(new Date()));
-
lastDay()
возвращает последний день в месяце вызывающего экземпляра объектаDate
. Пример:var d = new Date(); alert(d.lastDay());
var d = new Date(); alert(d.lastDay());
- Хотя это и не метод, вы можете получить английское длинное имя месяца из
Date.monthNames
массиваDate.monthNames
. Передайте индекс в диапазоне от 0 до 11. Пример:alert(Date.monthNames[0])
Методы, связанные с _Date
вместо его экземпляров, назначаются непосредственно _Date
, как в _Date.UTC = function(date)
. Параметр date
определяет либо базовую ссылку на объект Date
либо ссылку _Date
. Для этого _Date
методы, связанные с экземплярами _Date
. Внутри метода доступ к экземпляру Date
осуществляется через this.instance
.
Вы будете следовать предыдущему протоколу для поддержки Array
, String
и других основных объектов — за исключением Math
. В отличие от других основных объектов, вы не можете создавать объекты Math
. Вместо этого Math
— это просто заполнитель для хранения статических свойств и методов. По этой причине я по-разному отношусь к Math
, объявляя переменную _Math
инициализированную для пустого объекта, и назначая свойства и методы непосредственно этому объекту.
Первым шагом в инициализации _Math
является getOwnPropertyNames()
метода getOwnPropertyNames()
Object
(реализованного в ECMAScript 5 и поддерживаемого современными настольными браузерами) для возврата массива всех свойств (перечисляемых или нет), найденных непосредственно в объекте аргумента, то есть Math
, Затем в листинге 1 каждое свойство (функция или иное) _Math
перед введением новых свойств / методов (если они еще не представлены):
-
GOLDEN_RATIO
является константой золотогоGOLDEN_RATIO
, о котором я упоминал в предыдущей статье. Пример:alert(Math.GOLDEN_RATIO);
-
rnd(limit)
возвращает целое число в диапазоне от 0 до значения, которое меньше значенияlimit
. Пример:alert(Math.rnd(10));
-
rndRange(min, max)
возвращает случайное целое число в диапазоне от значенияmin
до значенияmax
. Пример:alert(Math.rndRange(10, 20));
-
toDegrees(radians)
преобразует значениеradians
в эквивалентное значение в градусах и возвращает это значение. Пример:alert(Math.toDegrees(Math.PI));
-
toRadians(degrees)
преобразует значение вdegrees
в эквивалентное значение в радианах и возвращает это значение. Пример:alert(Math.toRadians(180));
-
trunc(n)
удаляет дробную часть из положительного или отрицательного числа, переданногоn
и возвращает всю часть. Пример:alert(Math.trunc(5.8));
Каждый метод генерирует исключение, обозначающее недопустимый аргумент, когда он обнаруживает аргумент, который не относится к типу Number
.
Зачем создавать библиотеку дополнений вместо создания отдельных служебных объектов (таких как DateUtil
или MathUtil
)? Библиотека служит массивной прокладкой для обеспечения согласованной функциональности во всех браузерах. Например, объект Math
Firefox 25.0 предоставляет метод trunc()
тогда как этот метод отсутствует в Opera 12.16. Моя библиотека гарантирует, что метод trunc()
всегда доступен.
Тестирование и использование новой библиотеки расширения базовых объектов
Теперь, когда у вас была возможность изучить библиотеку, вы захотите попробовать ее. Я создал пару скриптов, которые тестируют различные новые возможности _Date
и _Math
, и создал пару более практичных скриптов, которые более полно используют библиотеку. В листинге 2 представлен HTML-документ, в который _Date
скрипт для тестирования _Date
.
<! DOCTYPE html> <HTML> <Голова> <Название> Тестер дополненной даты </ Title> <script type = "text / javascript" src = "ajscolib.js"> </ Скрипт> </ HEAD> <Тело> <Скрипт> var Date = ca_tutortutor_AJSCOLib._Date; переменная дата = новая дата (); оповещение («Текущая дата:» + дата); alert («Текущая дата:» + date.toString ()); var dateCopy = date.copy (); alert («Копировать текущую дату:» + date.toString ()); предупреждение («Текущая дата == Копия текущей даты:» + (date == dateCopy)); alert ("Isleap" + date.toString () + ":" + date.isLeap ()); alert («Isleap 1 июля 2012 г .:» + Date.isLeap (новая дата (2012, 6, 1))); alert («Последний день:» + date.lastDay ()); alert («Названия месяцев:» + Date.monthNames); </ Скрипт> </ Body> </ Html>
Листинг 2: Тестирование «расширенного» объекта Date
При работе с этой библиотекой вы не захотите указывать ca_tutortutor_AJSCOLib._Date
и, вероятно, не захотите указывать _Date
. Вместо этого вы захотите указать Date
как будто вы работаете с самим основным объектом. Вам не нужно менять свой код, чтобы изменить ссылки Date
на что-то другое. К счастью, вам не нужно этого делать.
Первая строка в сценарии присваивает ca_tutortutor_AJSCOLib._Date
значение Date
, фактически удаляя весь доступ к ca_tutortutor_AJSCOLib._Date
объекту Date
. Это причина для указания var _Date_ = Date;
в библиотеке. Если бы я ссылался на Date
вместо _Date_
в коде библиотеки, вы бы _Date_
«слишком много рекурсии» (и, возможно, другие проблемы).
Остальная часть кода выглядит знакомой тем, кто работал с Date
. Тем не менее, есть небольшой сбой. Что выводится при вызове alert("Current date: " + date);
? Если бы вы использовали основной объект Date
, вы бы увидели Current date:
после строкового представления текущей даты. В текущем контексте, однако, вы наблюдаете Current date:
за ней следует числовое значение в миллисекундах.
toString()
против valueOf()
Проверьте преобразования объекта в примитив в JavaScript, чтобы узнать, почему alert("Current date: " + date);
приводит к строковому или числовому представлению date
.
Давайте применим «расширенный» объект Date
для практического использования, например, для создания страницы календаря. Сценарий будет использовать document.writeln()
для вывода HTML-кода этой страницы на основе элемента <table>
. _Date
два варианта конструктора _Date
вместе с getFullYear()
, getMonth()
, getDay()
, lastDay()
и getDate()
и свойство monthNames
. Проверьте Листинг 3.
<! DOCTYPE html> <HTML> <Голова> <Название> Календарь </ Title> <script type = "text / javascript" src = "ajscolib.js"> </ Скрипт> </ HEAD> <Тело> <Скрипт> var Date = ca_tutortutor_AJSCOLib._Date; переменная дата = новая дата (); var year = date.getFullYear (); var month = date.getMonth (); document.writeln ("<table border = 1>"); document.writeln ("<th bgcolor = # eeaa00 colspan = 7>"); document.writeln ("<центр>" + Date.monthNames [месяц] + "" + год + "</ Центр>"); document.writeln ( "</ й>"); document.writeln ("<tr bgcolor = # ff7700>"); document.writeln ( "<TD> <B> <центр> S </ центр> </ B> </ TD>"); document.writeln ( "<TD> <B> <центр> М </ центр> </ B> </ TD>"); document.writeln ( "<TD> <B> <центр> Т </ центр> </ B> </ TD>"); document.writeln ( "<TD> <B> <центр> W </ центр> </ B> </ TD>"); document.writeln ( "<TD> <B> <центр> Т </ центр> </ B> </ TD>"); document.writeln ( "<TD> <B> <центр> F </ центр> </ B> </ TD>"); document.writeln ( "<TD> <B> <центр> S </ центр> </ B> </ TD>"); document.writeln ( "</ TR>"); var dayOfWeek = new Date (year, month, 1) .getDay (); вар день = 1; для (переменная строка = 0; строка <6; строка ++) { document.writeln ( "<TR>"); для (var col = 0; col <7; col ++) { var row; if ((row == 0 && col <dayOfWeek) || day> date.lastDay ()) { document.writeln ("<td bgcolor = # cc6622>"); document.writeln (""); } еще { if (day == date.getDate ()) document.writeln ("<td bgcolor = # ffff00>"); еще если (день% 2 == 0) document.writeln ("<td bgcolor = # ff9940>"); еще document.writeln ( "<TD>"); document.writeln (день ++); } document.writeln ( "</ TD>"); } document.writeln ( "</ TR>"); } document.writeln ( "</ таблицы>"); </ Скрипт> </ Body> </ Html>
Листинг 3: Использование «расширенного» объекта Date
для создания страницы календаря
Чтобы создать реалистичную страницу календаря, нам нужно знать, в какой день недели наступает первый день месяца. Выражение new Date(year, month, 1).getDay()
дает нам необходимую информацию (0 для воскресенья, 1 для понедельника и т. Д.), dayOfWeek
присваивается dayOfWeek
. Каждый квадрат в верхней строке, индекс столбца которого меньше, чем dayOfWeek
, остается пустым.
На рисунке 1 показан пример страницы календаря.
Рисунок 1: Текущий день выделен желтым цветом.
В листинге 4 представлен HTML-документ, в который _Math
скрипт для тестирования _Math
.
<! DOCTYPE html> <HTML> <Голова> <Название> Дополненный тестер по математике </ Title> <script type = "text / javascript" src = "ajscolib.js"> </ Скрипт> </ HEAD> <Тело> <Скрипт> var Math = ca_tutortutor_AJSCOLib._Math; оповещение ("Math.GOLDEN_RATIO:" + Math.GOLDEN_RATIO); пытаться { alert ("Math.rnd (null):" + Math.rnd (null)); } поймать { alert («нулевое значение не поддерживается.»); } alert ("Math.rnd (10):" + Math.rnd (10)); для (var i = 0; i <10; i ++) alert (Math.rndRange (5, 9)); пытаться { alert ("Math.toDegrees (null):" + Math.toDegrees (null)); } поймать { alert («нулевые градусы не поддерживаются»); } alert ("Math.toDegrees (Math.PI):" + Math.toDegrees (Math.PI)); пытаться { alert ("Math.toRadians (null):" + Math.toRadians (null)); } поймать { alert («нулевые радианы не поддерживаются»); } alert ("Math.toRadians (180):" + Math.toRadians (180)); пытаться { alert ("Math.trunc (null):" + Math.trunc (null)); } поймать { alert («нулевое значение не поддерживается.»); } alert ("Math.trunc (10.83):" + Math.trunc (10.83)); alert ("Math.trunc (-10.83):" + Math.trunc (-10.83)); </ Скрипт> </ Body> </ Html>
Листинг 4: Тестирование «дополненного» объекта Math
Давайте применим «расширенный» объект Math
для практического использования, например, для отображения кардиоидной кривой , которая представляет собой плоскую кривую, очерченную точкой по периметру круга, который вращается вокруг неподвижного круга того же радиуса. Скрипт будет использовать rndRange()
Math
: rndRange()
, toRadians()
, cos()
и sin()
. Проверьте Листинг 5.
<! DOCTYPE html> <HTML> <Голова> <Название> кардиоида </ Title> <script type = "text / javascript" src = "ajscolib.js"> </ Скрипт> </ HEAD> <Тело> <canvas id = "canvas" width = "300" height = "300"> холст не поддерживается </ Холст> <Скрипт> var Math = ca_tutortutor_AJSCOLib._Math; var canvas = document.getElementById ("canvas"); var canvasctx = canvas.getContext ("2d"); var width = document.getElementById ("canvas"). width; var height = document.getElementById ("canvas"). height; canvasctx.fillStyle = "# 000"; canvasctx.fillRect (0, 0, ширина, высота); canvasctx.fillStyle = "RGB (" + Math.rndRange (128, 255) + "," + Math.rndRange (128, 255) + "," + Math.rndRange (128, 255) + ")"; canvasctx.beginPath (); для (var angleDeg = -180,0; angleDeg <180,0; angleDeg + = 0,1) { var angle = Math.toRadians (angleDeg); // Оценить уравнение кардиоидной кривой. Это производит радиус для // заданный угол. Примечание: [r, угол] - полярные координаты. var r = 60,0 + 60,0 * Math.cos (угол); // Преобразование полярных координат в прямоугольные. добавлять // ширина / 2 и высота / 2, чтобы переместить начало кривой в центр // холста. (По умолчанию в качестве источника используется верхний левый угол холста.) var x = r * Math.cos (угол) + ширина / 2; var y = r * Math.sin (угол) + высота / 2; если (угол == 0,0) canvasctx.moveTo (x, y); еще canvasctx.lineTo (x, y) } canvasctx.closePath (); canvasctx.fill (); </ Скрипт> </ Body> </ Html>
Листинг 5: Использование «расширенного» объекта Math
для создания кривой кардиоида
В листинге 5 для beginPath()
кардиоидной кривой используются элемент canvas из HTML5 и API, который создается в виде многоугольника с помощью beginPath()
, moveTo()
, lineTo()
и closePath()
холста контекста. Каждый компонент цвета заливки кривой выбирается случайным образом с помощью rndRange()
. Его аргументы гарантируют, что компонент не слишком темный. Кривая заполняется с помощью метода fill()
контекста canvas.
Рисунок 2 показывает красочную кардиоидную кривую.
Рисунок 2: Перезагрузите страницу, чтобы изменить цвет кривой.
Вывод
В этой статье показано, как создать библиотеку, которая дополняет основные объекты JavaScript, не дополняя их напрямую. Публичный интерфейс библиотеки переносим между браузерами, хотя возможно, что для реализации может потребоваться настройка на совместимость, производительность или другие причины. В качестве упражнения добавьте в эту библиотеку усовершенствования Array
, Boolean
, Number
и String
моей предыдущей статьи.