Слава Україні
Glory to Ukraine
Save the World
Жыве Беларусь
Live Belarus



Урок - lesson19

Главная » Курсы » Курс JavaScript » Урок - lesson19

Обучающий онлайн курс
JavaScript

Лицензия: Лицензия Creative Commons.
۞ → Читать Урок lesson19. Уроки Самоделкина/Урок 19
d width="15" background="img/jslft.gif" tppabs="http://froland2.narod.ru/img/jslft.gif">
</td

19. Объект String
Свойство length, методы обработки строк

  • создание и использование объекта;
  • свойство length;
  • краткое описание ряда методов;
  • методы charAt(), slice();
  • методы lastIndexOf(), substring();
  • метод fromCharCode();
  • метод concat();
  • методы charCodeAt(), indexOf(), substr();
  • методы split(), toLowerCase(), toUpperCase().

Создание объекта String

Создать строковый объект можно с помощью конструктора new:

var имя_переменной = new String("некая_строка");

Однако гораздо чаще используется обычное присвоение:

var имя_переменной = "некая_строка";

В обоих случаях происходит почти одно и то же: интерпретатор создаёт экземпляр объекта String.

Почему «почти»?

Когда мы создаём строку вторым способом, то, говоря специальным языком, создаём не объект, а строковый литерал. Если мы вызываем для него метод, то JavaScript автоматически конвертирует его во временный объект String, вызывает этот метод, а затем уничтожает временный объект.

Если же мы создаём полноценный объект с помощью конструктора new, то мы сами же должны и управлять его поведением на всём протяжении скрипта. А поведение его может оказаться непредсказуемым.

Отсюда вывод: использовать конструктор нужно только в тех случаях, когда без этого не обойтись. Некоторые из этих случаев мы рассмотрим в процессе знакомства с методами объекта String.

Ну и совсем детский вопрос: почему во втором случае интерпретатор угадывает, что нужно создать именно объект String?

Потому что значение переменной было заключено в кавычки.

Значение объекта String (то, что я только что назвал строковым литералом) всегда должно быть в кавычках.

А может ли следующее выражение быть верным?

var имя_переменной = new String(некая_строка);

Может, если некая_строка — это имя переменной, на которую уже была назначена какая-то строка. Но само имя переменной не будет значением объекта String!

Примечание: если воспринимать данное выражение буквально, то оно неверно, поскольку предполагаемое «имя переменной» записано русскими буквами, что запрещено в JavaScript.

Примечание: JavaScript чувствителен к регистру, поэтому всегда будьте внимательны при употреблении больших и маленьких букв в названиях свойств и методов!

Свойства объекта String

Объект String имеет три свойства:

  • constuctor
  • length
  • prototype

Свойства constuctor и prototype принадлежат объекту Object и наследуются всеми остальными объектами. О них мы поговорим, когда будем исследовать Object.

Свойство length

Как вы, наверно, уже догадались, это длина строки, то есть количество символов в строке.

var stroka = "Наука умеет много гитик";
var dlina = stroka.length
// Выводим количество символов:
document.write("Количество символов в переменной 'stroka': " + dlina);

Результат:

То есть 20 букв и 3 пробела.

Примечание для особо пытливых:

В методе document.write() нашего примера выводится текст, составленный из строкового выражения в кавычках и переменной dlina с численным, то есть другим типом данных. Это возможно, так как JavaScript является слабо типизированным языком, то есть жёстко определять типы данных не требуется. В некоторых случаях (но не в этом) подобное небрежение может привести к нежелательным результатам, поэтому следует отдавать себе отчёт в том, какие типы данных мы используем.

Для подстраховки можно воспользоваться приведением, как в жёстко типизированных языках. Чтобы привести переменную dlina к строковому типу, можно воспользоваться методом toString(10), где (10) означает, что мы переводим в строку десятичное значение.

document.write("Количество символов в переменной 'stroka': " + dlina.toString(10));

Методы объекта String

Методов у этого объекта очень много. Чтобы не запутаться, уместно разбить их по категориям.

Методы обработки строк

Иногда их ещё называют стандартными методами. Этими методами можно программно изменять содержание строк, создавать на основе существующих строк новые строки, разбирать строки на массивы и, наоборот, создавать из массивов отдельные строковые объекты. Можно также выполнять в строке поиск заданного слова, части слова или отдельного символа (искомую часть строки обычно называют подстрокой [substring]), получить численный код символа или, наоборот, вывести символ по заданному численному коду.

Методы форматирования строк

Эти методы в основном дублируют форматирующие тэги HTML. Но благодаря их использованию в JavaScript можно создавать динамичные страницы, в которых форматирование может меняться либо по щелчку пользователя, либо в зависимости от разрешения экрана, типа браузера или каких-нибудь других условий (времени суток, например; да мало ли диковинного и забавного можно напридумывать).

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

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

Методы по полочкам

В этом разделе я даю краткие описания методов объекта String, которые будут рассмотрены в сегодняшнем уроке.

Метод charAt()

Возвращает символ, занимающий в строке указанную позицию.

Синтаксис

строка.charAt(индекс)

Аргумент

индекс — номер символа в строке. Индекс первого символа равен 0. Индекс последнего, соответственно, — строка.length-1.

Примечания

Если скобки оставить пустыми, метод возвратит нулевой (то есть первый) символ.

Если индекс превышает длину строки, возвращается значение NaN — свойство ядра, представляющее Not-A-Number/Не-Число (это свойство мы рассмотрим, когда будем учиться обрабатывать ошибки).

Примеры

"Бармалей".charAt(0)                     // возвращает "Б"
"Бармалей".charAt()                      // возвращает "Б"
"Бармалей".charAt(2)                     // возвращает "р"
"Бармалей".charAt("Бармалей".length-1)   // возвращает "й"
"Бармалей".charAt(32)                    // возвращает NaN

Метод charCodeAt()

Возвращает число, равное десятичному значению Unicode указанного символа.

Синтаксис

строка.charCodeAt(индекс)

Аргумент

индекс — номер символа в строке. Индекс первого символа равен 0. Индекс последнего, соответственно, — строка.length-1.

Примечание

Если индекс указывает несуществующую позицию, то возвращается NaN.

Примеры

"Строка".charCodeAt(0) /* Десятичный код русской буквы "С"
                          верхнего регистра: 1057 */
"Строка".charCodeAt(1).toString(16) /* 16-ричный код русской буквы "т"
                                       нижнего регистра: 442 */
"Строка".charCodeAt(8) // NaN (нет такой позиции)

Примечание: во втором примере мы воспользовались также методом toString() объекта Object, который конвертирует любое число в строку значения этого числа в исчислении, заданном в аргументе (2, 8, 10 или 16). Именно этот метод использован в моих таблицах Unicode для отображения 16-ричных значений.

Метод fromCharCode()

Возвращает строку символов Unicode, числовые коды которой указаны в качестве параметров.

Это статический метод. В качестве строкового объекта используется базовый объект String собственной персоной (см. урок 18 об объектах и экземплярах).

Синтаксис

String.fromCharCode(номер1 [, номер2, ..., номерN])

Аргументы

номерN — числовой код символа (их может быть сколько угодно — в пределах разумного, конечно).

Примечания

IE4+, NN6+ поддерживают систему кодов Unicode, более старые версии — ISO-Latin 1.

Mozilla поддерживает Unicode.

Opera8+ поддерживает Unicode, причём корректнее, чем другие браузеры; о более старых версиях сведений не имею.

Примеры

String.fromCharCode(1040, 1085, 1076, 1088, 1077, 1081) // возвращает моё имя
String.fromCharCode(1078, 1086, 1087, 1072) /* возвращает
                                              не очень приличное слово*/

Метод indexOf()

Производит поиск строки, указанной аргументом, начиная с начала исходной строки, а возвращаемый индекс точно так же отсчитывается от ее начала, то есть от 0.

Синтаксис

строка.indexOf(строка_поиска [, индекс])

Аргументы

crpoкa_noискa — подстрока, в которой надо произвести поиск.

индекс — индекс символа, с которого начинается поиск; если этот аргумент не введён, поиск производится от начала исходной строки.

Примеры

 "Абракадабра".indexOf("А")    // возвращает 0
//0123...
 "Абракадабра".indexOf("а")    // возвращает 3

Метод lastIndexOf()

Производит поиск строки, указанной аргументом, начиная с конца исходной строки, и возвращает индекс ее первого вхождения; возвращаемый индекс отсчитывается от ее начала, то есть от 0.

Непонятно? Потерпите чуть-чуть.

Синтаксис

строка.lastIndexOf(строка_поиска [, индекс])

Аргументы

crpoкa_noискa — подстрока, в которой надо произвести поиск.

индекс — индекс символа, с которого начинается поиск; если этот аргумент не введён, поиск производится от конца исходной строки.

Примеры

 "Абракадабра".lastIndexOf("а")    // возвращает 10
//012345678910
 "Абракадабра".lastIndexOf("а", 9)    // возвращает 7

Метод slice()

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

Синтаксис

строка.slice(индекс1 [, индекс2])

Аргументы

индекс1 — индекс строки, с которого начинается подстрока. Индекс первого символа равен 0.

индекс2 — индекс строки, следующий за последним символом подстроки.

Примечания

Аргумент индекс2 не включается в подстроку. Чтобы из строки "пространство" извлечь подстроку "транс", последним параметром должен быть символ, идущий после «с»:

"Пространство".slice(4, 9)

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

Если параметр второго аргумента отрицателен, то отсчет конечного индекса производится от конца строки. При этом индекс2 соответствует последнему символу подстроки. Обратный отсчёт символов тоже с 0.

Примеры

"Бармалей".slice(0, 3)                  // возвращает "Бар"
"Бармалей".slice(3, 6)                  // возвращает "мал"
"Бармалей".slice(5)                     // возвращает "лей"
"Бармалей".slice(3, -2)                 // возвращает "мал"
"Бармалей".slice(5, 35)                 // возвращает "лей"

Метод substr()

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

Если длина не задана, то возвращается подстрока, начиная с данной позиции и до конца исходной строки.

Если длина отрицательна или равна нулю, то возвращается пустая строка.

Синтаксис

строка. substr(индекс [, длина])

Аргументы

индекс — начальная позиция подстроки в исходной строке.

длина — длина подстроки.

Примечания

Позиции символов строки нумеруются от нуля до строка.length-1. Если позиция больше или равна строка.length, то возвращается пустая строка. Если позиция отрицательна, то она трактуется как смещение от конца строки и заменяется на строка.length + индекс, то есть фактически даёт величину больше, чем строка.length

Внимание! Если позиция отрицательна, то Internet Explorer ошибочно заменяет ее на 0, поэтому в целях совместимости этот вариант использовать не следует.

Пример

"Пространство".substr(4, 5)  // возвращает "транс"

Метод substring()

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

Синтаксис

строка.substring(индекс1, индекс2)

Аргументы

индекс1 — индекс строки, с которого начинается подстрока. Индекс первого символа равен 0.

индекс2 — индекс строки, следующий за последним символом подстроки.

Примечания

Порядок индексов не важен: наименьший из них считается начальным..

Больший параметр не включается в подстроку.

Если второй параметр больше длины исходной строки, то возвращается подстрока с начальной позицией индекс1 до конца строки.

Отличия от slice()

Оба индекса обязательны.

Не используется отрицательное значение индекса.

Начало и конец подстроки зависят не от порядка индексов, а от сравнения их величин.

Может быть, этого описания вам хватит. Попробуйте перейти сразу к домашним заданиям. Если выполнение заданий вас затруднит, читайте весь урок, в котором эти методы «разжёваны».

Методы обработки строк

Задача 1. Из полного адреса web-документа вычленяем имя файла

Первый вариант: используем методы charAt(), slice().

Допустим, у нас есть следующий адрес:

http://froland2.narod.ru/objects/string.html

Нам надо извлечь из него имя файла: string.html.

Значит, нужно найти последний слэш, а затем отрезать и вывести кусок строки, идущий после него.

Слэш будем искать методом charAt().

Метод charAt()

Возвращает символ, занимающий в строке указанную позицию.

Синтаксис

строка.charAt(индекс)

Аргумент

индекс — номер символа в строке. Индекс первого символа равен 0. Индекс последнего, соответственно, — строка.length-1.

Примечания

Если скобки оставить пустыми, метод возвратит нулевой (то есть первый) символ.

Если индекс превышает длину строки, возвращается значение NaN — свойство ядра, представляющее Not-A-Number/Не-Число (это свойство мы рассмотрим, когда будем учиться обрабатывать ошибки).

Примеры

"Бармалей".charAt(0)                     // возвращает "Б"
"Бармалей".charAt()                      // возвращает "Б"
"Бармалей".charAt(2)                     // возвращает "р"
"Бармалей".charAt("Бармалей".length-1)   // возвращает "й"
"Бармалей".charAt(32)                    // возвращает NaN

Чтобы запустить метод, этот индекс мы должны знать. Конечно, можно сосчитать его на пальцах в нашей исходной строке. Но смысл-то задачи в том, чтобы правильно отсекать имя файла из любого введённого адреса. Поэтому надо сделать, чтобы скрипт сам искал нужный индекс.

Чтобы найти нужный индекс, надо перебрать символы циклом. Начнём строить код. Сначала сделаем упрощённый вариант для нашей заданной строки. Объявим переменные.

var str = "http://froland2.narod.ru/objects/string.html"
var endStr = str.length; // длина исходной строки
var symbol;              // переменная для поиска слэша
var str2;                // переменная для строки, которую мы хотим получить
var i;                   // счётчик цикла

В данном случае цикл нужно запускать с конца, задом наперёд, чтобы не наткнуться на непрошеные слэши.

for (i=endStr-1; i>=0; i--)
{
symbol = str.charAt(i);
    if (symbol=="/")
    . . . . . . . . . . . .

Итак, если переменная захватила слэш, то...

...то нам уже хватает данных, чтобы составить обрезанную подстроку. А для этого нам пригодится метод slice().

Метод slice()

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

Синтаксис

строка.slice(индекс1 [, индекс2])

Аргументы

индекс1 — индекс строки, с которого начинается подстрока. Индекс первого символа равен 0.

индекс2 — индекс строки, следующий за последним символом подстроки.

Примечания

Аргумент индекс2 не включается в подстроку. Чтобы из строки "пространство" извлечь подстроку "транс", последним параметром должен быть символ, идущий после «с»:

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

Если второй параметр отрицателен, то отсчет конечного индекса производится от конца строки. При этом индекс2 соответствует последнему символу подстроки. Обратный отсчёт символов тоже с 0.

Примеры

"Бармалей".slice(0, 3)                  // возвращает "Бар"
"Бармалей".slice(3, 6)                  // возвращает "мал"
"Бармалей".slice(5)                     // возвращает "лей"
"Бармалей".slice(3, -2)                 // возвращает "мал"
"Бармалей".slice(5, 35)                 // возвращает "лей"

Теперь можно вернуться к нашей задаче.

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

for (i=endStr-1; i>=0; i--)
{
symbol = str.charAt(i);
    if (symbol=="/")
    {
    str2 = str.slice(i+1);
    document.write(str2);
    break;
    }
}

А зачем break?

В нашей исходной строке несколько слэшей. Если мы не поставим break, то JavaScript продолжит свои изыскания и выдаст

string.htmlobjects/string.htmlfroland2.narod.ru/objects/string.html/froland2.narod.ru/objects/
string.html

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

function slicePath(str) {
    var endStr = str.length;
    var symbol;
    var str2;
    var i;
    for (i=endStr-1; i>=0; i--)
    {
    symbol = str.charAt(i);
        if (symbol=="/")
        {
        str2 = str.slice(i+1);
        document.write(str2);
        break;
        }
    }
}

А теперь определим этой функцией имя файла страницы, на которой мы находимся.

<script type="text/javascript">
var myPath = self.location.href
slicePath(myPath)
</script>

Результат:

Второй вариант: используем методы lastIndexOf(), substring().

Этот вариант проще, он делается безо всяких циклов и ветвлений. Это возможно благодаря методу lastIndexOf().

Метод lastIndexOf()

Производит поиск строки, указанной аргументом, начиная с конца исходной строки, и возвращает индекс ее первого вхождения; возвращаемый индекс отсчитывается от ее начала, то есть от 0.

Непонятно? Потерпите чуть-чуть.

Синтаксис

строка.lastIndexOf(строка_поиска [, индекс])

Аргументы

crpoкa_noискa — подстрока, в которой надо произвести поиск.

индекс — индекс символа, с которого начинается поиск; если этот аргумент не введён, поиск производится от конца исходной строки.

Абракадабра? Давайте разберёмся наглядно. Возьмём эту «абракадабру» в качестве исходной строки и поищем в ней «а», благо этих «а» там много (первая не считается: она у меня в верхнем регистре, а мы ищем в нижнем).

Если индекс не введён, поиск начинается от самого конца, сразу натыкается на последнюю «а» и выдаёт результат.

А теперь поменяйте картинку и посмотрите, как метод будет работать с разными индексами.

Результат: 10

Демонстрация обрывается на индексе 3. А что будет, если мы запросим 2, 1 или 0?

В этих случаях результат будет -1 [минус один], то есть false: не найдено!

Надеюсь, теперь вы уяснили, как работает метод.

Примечание: первая буква «А» написана в верхнем регистре, поэтому не входит в диапазон поиска. А как «обманывать» регистрово-чувствительный JavaScript, мы тоже узнаем, но попозже.

Вернёмся к нашей задаче.

Вот так мы можем проверить, где лежит наш последний слэш.

symbol = str.lastIndexOf("/");

А для формирования подстроки воспользуемся методом substring().

А почему не slice()? Да только потому, что мы его уже знаем. А так у меня есть повод подсунуть вам ещё один метод.

Метод substring()

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

Синтаксис

строка.substring(индекс1, индекс2)

Аргументы

индекс1 — индекс строки, с которого начинается подстрока. Индекс первого символа равен 0.

индекс2 — индекс строки, следующий за последним символом подстроки.

Примечания

Порядок индексов не важен: наименьший из них считается начальным..

Больший параметр не включается в подстроку.

Если второй параметр больше длины исходной строки, то возвращается подстрока с начальной позицией индекс1 до конца строки.

Отличия от slice()

Оба индекса обязательны.

Не используется отрицательное значение индекса.

Начало и конец подстроки зависят не от порядка индексов, а от сравнения их величин.

Наша искомая подстрока будет выглядеть следующим образом:

str2 = str.substring(symbol+1, str.length);

Теперь укатаем это в функцию:

function slicePath2(str) {
    var symbol;
    var str2;
    symbol = str.lastIndexOf("/");
    str2 = str.substring(symbol+1, str.length);
    document.write(str2);
}

Результат:

Задача 2. Создаём таблицу символов Unicode

Используемый метод: fromCharCode().

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

Например:

для отображения символа ó нужно ввести в HTML-код &#243;

для отображения символа Æ нужно ввести в HTML-код &#198;

Числовое значение конструкции &#номер; и есть код символа Unicode.

Символов в Unicode несколько тысяч, запомнить их нереально. Но даже и сотню-другую запоминать не надо, можно воспользоваться таблицей. А где её взять? Сделать! Вот этим мы сейчас и займёмся.

Вот кусочек такой таблицы:

Вспомним, как в 6-м уроке мы создавали таблицу умножения циклом for. Сейчас нам потребуется нечто подобное.

Давайте сначала сделаем болванку HTML для 1 ряда таблицы Unicode. Столбцов в ряду сделаем 20 (это можно проделать в уме или на бумаге, я просто демонстрирую для наглядности).

<table>
<tr>
    <td>1</td>
    <td>2</td>
    <td>3</td>
    <td>4</td>
    <td>5</td>
    <td>6</td>
    <td>7</td>
    <td>8</td>
    <td>9</td>
    <td>10</td>
    <td>11</td>
    <td>12</td>
    <td>13</td>
    <td>14</td>
    <td>15</td>
    <td>16</td>
    <td>17</td>
    <td>18</td>
    <td>19</td>
    <td>20</td>
</tr>
<tr>
    <td>[код символа 1]</td>
    <td>[код символа 2]</td>
    <td>[код символа 3]</td>
    <td>[код символа 4]</td>
    <td>[код символа 5]</td>
    <td>[код символа 6]</td>
    <td>[код символа 7]</td>
    <td>[код символа 8]</td>
    <td>[код символа 9]</td>
    <td>[код символа 10]</td>
    <td>[код символа 11]</td>
    <td>[код символа 12]</td>
    <td>[код символа 13]</td>
    <td>[код символа 14]</td>
    <td>[код символа 15]</td>
    <td>[код символа 16]</td>
    <td>[код символа 17]</td>
    <td>[код символа 18]</td>
    <td>[код символа 19]</td>
    <td>[код символа 20]</td>
</tr>
<tr>
    <td>
        и.т.д., и т.д., и т.д.
    </td>
</tr>
</table>

Для вывода самих символов воспользуемся методом fromCharCode().

Метод fromCharCode()

Возвращает строку символов Unicode, числовые коды которой указаны в качестве аргументов.

Это статический метод. В качестве строкового объекта используется базовый объект String собственной персоной (см. урок 18 об объектах и экземплярах).

Синтаксис

String.fromCharCode(номер1 [, номер2, ..., номерN])

Аргументы

номерN — числовой код символа.

Примечания

IE4+, NN6+ поддерживают систему кодов Unicode, более старые версии — ISO-Latin 1.

Mozilla поддерживает Unicode.

Opera8+ поддерживает Unicode, причём корректнее, чем другие браузеры; о более старых версиях сведений не имею.

Примеры

String.fromCharCode(1040, 1085, 1076, 1088, 1077, 1081) // возвращает моё имя
String.fromCharCode(1078, 1086, 1087, 1072) /* возвращает
                                              не очень приличное слово*/

Но чтобы применить этот медод, мы должны знать, что вводить... Помните, в таблице умножения мы использовали переменные-счётчики и для подсчёта ячеек таблицы, и для вывода содержания? Подобное мы будем использовать и здесь. Это похоже на решение школьного уравнения с неизвестными.

Не будем делать таблицу на весь Unicode, в котором встречаются символы с номерами больше 20000. Для начала ограничимся первыми 580. Почему 580? Первые 563 символа содержат практически исчерпывающий набор расширенной латиницы. Дальше наступает небольшой перерыв до 592-го символа, после чего появляются экзотические дополнительные символы, многие из которых дублируют символы предыдущего набора. А так как мы задали таблицу в 20 столбцов, то на 20 в этом пустом промежутке делится как раз 580.

Рядов у нас получается 58 (580:20=29, 29 — для номеров и 29 — для символов). Но поскольку каждые 2 ряда взаимосвязаны данными (фактически одни и те же данные, только в разных представлениях), по одному счётчику мы пустим 2 ряда. То есть шагов для счётчика рядов будет 29 (от 0 до 28). А 20 шагов счётчика столбцов сделаем от 1 до 20.

(Если вы не поняли и половины вышеизложенного — не беда. Сейчас начнём делать — и всё встанет на свои места.)

Объявим переменные счётчиков.

var i, j; // i - для рядов (<tr>), j - для столбцов (<td>)

Формируем остов таблицы:

document.write("<table width=\"600\" border=\"1\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">")
for (i = 0; i <= 28; i++)
{
document.write("<tr>");  // для номеров
    . . .
    . . .
    . . .
document.write("</tr>")
document.write("<tr>");  // для символов
    . . .
    . . .
    . . .
document.write("</tr>")
}
document.write("</table>")

Туда, где сейчас стоят точки, нужно вставить циклы для столбцов. В них же будет и формула для вывода содержания. Давайте подумаем, как сделать, чтобы ячейки заполнились подряд номерами от 1 до 580.

Если j у нас от 1 до 20, то с первой парой рядов понятно: просто выводим j (хотя, как сейчас выяснится, и не совсем просто).

Во второй паре рядов нам нужно к каждому номеру прибавить 20, в третьей — 40 (то есть 2×20), в четвёртойй — 60 (то есть 3×20) и т.д.

Обратимся к уже определённой нами переменной i.

В первой паре рядов она равна 0, во второй — 1, в третьей — 2...

Смотрите!

20*i для первой пары рядов будет 0, для второй — 20, для третьей — 40...

Улавливаете?

Формула 20*i+j и даёт нам нужную последовательность. Кстати, понятно, почему i нужно задать от нуля?

Для ряда с номерами:

for (j = 1; j <= 20; j++)
{
document.write(<td width=\"5%\" align=\"center\">")
document.write(20*i+j)
document.write("</td>")
}

Для ряда с символами:

for (j = 1; j <= 20; j++)
{
document.write(<td width=\"5%\" align=\"center\">")
document.write(String.fromCharCode(20*i+j))
document.write("</td>")
}

Осталось вставить это в общий код:

document.write("<table width=\"600\" border=\"1\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">")
for (i = 0; i <= 28; i++)
{
document.write("<tr>");  // для номеров
    for (j = 1; j <= 20; j++)
    {
    document.write(<td width=\"5%\" align=\"center\">")
    document.write(20*i+j)
    document.write("</td>")
    }
document.write("</tr>")
document.write("<tr>");  // для символов
    for (j = 1; j <= 20; j++)
    {
    document.write(<td width=\"5%\" align=\"center\">")
    document.write(String.fromCharCode(20*i+j))
    document.write("</td>")
    }
document.write("</tr>")