Javascript — объект document

Особенности правильной интеграции Pop-up

В искусстве использования всплывающих окон на сайте критически важным условием является умение маркетолога грамотно выбирать форму и момент их появления. В идеале сообщение должно иметь мощный мотивирующий эффект при минимальном раздражающем влиянии. Чтобы окно не нервировало, не нужно демонстрировать его сразу после входа на страницу. Считается, что человеку для первичного восприятия контента нужно от 30 до 90 секунд, и только после этого у него могут возникнуть вопросы или желание для более глубокого взаимодействия. Оптимальное время появления Pop-up определяется индивидуально с помощью сплит-тестирования и аналитики.

Лучше воспринимаются всплывающие окна, которые демонстрируются после того, как пользователь просмотрел 40–70 % контента на странице. Такое поведение демонстрирует, что содержимое его заинтересовало, поэтому появление окна его, скорее всего, не оттолкнет. Хорошие результаты показывает алгоритм появления Pop-up, который привязан к попытке выхода с сайта. Этот вариант демонстрации реализуется путем наблюдения за перемещением курсора. Сложные алгоритмы способны определять, пытается ли пользователь уйти со страницы или просто переходит между вкладками одного сайта – это позволяет избежать дублирующих показов.

Сравнение строк

Как мы знаем из главы Операторы сравнения, строки сравниваются посимвольно в алфавитном порядке.


Тем не менее, есть некоторые нюансы.

  1. Строчные буквы больше заглавных:

  2. Буквы, имеющие диакритические знаки, идут «не по порядку»:

    Это может привести к своеобразным результатам при сортировке названий стран: нормально было бы ожидать, что будет после в списке.

Чтобы разобраться, что происходит, давайте ознакомимся с внутренним представлением строк в JavaScript.

Строки кодируются в UTF-16. Таким образом, у любого символа есть соответствующий код. Есть специальные методы, позволяющие получить символ по его коду и наоборот.

Возвращает код для символа, находящегося на позиции :

Создаёт символ по его коду

Также можно добавлять юникодные символы по их кодам, используя с шестнадцатеричным кодом символа:

Давайте сделаем строку, содержащую символы с кодами от до — это латиница и ещё некоторые распространённые символы:

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

Теперь очевидно, почему .

Символы сравниваются по их кодам. Больший код — больший символ. Код (97) больше кода (90).

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

«Правильный» алгоритм сравнения строк сложнее, чем может показаться, так как разные языки используют разные алфавиты.

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

К счастью, все современные браузеры (для IE10− нужна дополнительная библиотека Intl.JS) поддерживают стандарт ECMA 402, обеспечивающий правильное сравнение строк на разных языках с учётом их правил.

Для этого есть соответствующий метод.

Вызов str.localeCompare(str2) возвращает число, которое показывает, какая строка больше в соответствии с правилами языка:

  • Отрицательное число, если меньше .
  • Положительное число, если больше .
  • , если строки равны.

Например:

У этого метода есть два дополнительных аргумента, которые указаны в документации. Первый позволяет указать язык (по умолчанию берётся из окружения) — от него зависит порядок букв. Второй — определить дополнительные правила, такие как чувствительность к регистру, а также следует ли учитывать различия между и .

new Date(год, месяц, …)

создает новый объект дата с указанными датой и время.

7 чисел указывают год, месяц, день, час, минуты, секунды и миллисекунды (в указанном порядке):

var d = new Date(2018, 11, 24, 10, 33, 30, 0);

JavaScript считает месяцы от 0 до 11. Январь есть 0. Декабря есть 11.

6 чисел определяют год, месяц, день, час, минуты, секунды:

var d = new Date(2018, 11, 24, 10, 33, 30);

5 чисел определяют год, месяц, день, час и минуты:

var d = new Date(2018, 11, 24, 10, 33);

4 числа определяют год, месяц, день и час:

var d = new Date(2018, 11, 24, 10);

3 числа определяют год, месяц и день:


var d = new Date(2018, 11, 24);

2 числа определяют год и месяц:

var d = new Date(2018, 11);

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

console.log

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

examples/js/console.html

<script>

console.log("Hello World");

</script>

Try!

Большинство веб-браузеров предоставляют то, что называется «JavaScript console». Это дополнительное окно (которое не видно в нормально режиме), где браузер выводит предупреждения и ошибки, сгенерированные кодом JavaScript. Разработчики также могут выводить информацию в эту консоль с помощью вызова console.log().

Для того, чтобы увидеть консоль, вам нужно будет ее открыть. Если вы используете Chrome на OSX вы можете открыть консоль с помощью Command-Option-J.

JavaScript функции для работы с типами данных

Иногда в программе требуется преобразовать тип переменной. Рассмотрим основные функции, связанные с преобразованием типов:

преобразует указанную в параметре строку в целое число

Если есть второй параметр — система счисления — преобразование происходит по указанному основанию системы счисления (8, 10 или 16):

parseInt(«3.14») // результат = 3 parseInt(«-7.875») // результат = -7 parseInt(«435») // результат = 435 parseInt(«Вася») /* результат = NaN, то есть не является числом */ parseInt(«15» ,8) // результат = 13 Важно: Функция отсекает дробную часть числа. Чтобы округлить число необходимо использовать метод

преобразует указанную строку в число с плавающей разделительной точкой (десятичной):

parseFloat(«3.14») // результат = 3.14 parseFloat(«-7.875») // результат = -7.875 parseFloat («435») // результат = 435 parseFloat («Вася») /* результат = NaN, то есть не является числом */ parseFloat («17.5») // результат = 17.5 Важно: Обе функции и и используют в качестве параметра строку и преобразуют ее в число Кроме того, в javascript предусмотрены еще два способа преобразований:1

Обычные преобразования:

x = Number(x) // к числу x = String(x) // к строке x = Boolean(x) // к булеву типу2. Компактные преобразования:

x = +x // к числу x = x + » // к строке x = !!x // к булеву типу Функция javascript

служит для определения того, является ли значение выражения числом:

isNaN(123) 		/* результат false 
(то есть это - число) */
isNaN("50 рублей") 	/* результат true 
(то есть это - не число) */

Иногда можно получить такую ошибку JavaScript — — когда значение не является числом (а ожидается число):

var a=8; 
var b="pi";
var S=a*b; // S=NaN

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

var b; 
document.write(b); // b=undefined

Для того чтобы узнать текущий тип данных конкретной переменной в javascript используется функция :

typeof  33         // возвращает строку "number", 
typeof  "A String" // возвращает строку "string",
typeof  true       // возвращает строку "boolean", 
typeof  null       // возвращает строку "object"

Пример 1. Создайте сценарий:

  • с двумя строковыми переменными со значениями и ; с помощью операции конкатенации объедините строки;
  • с двумя числовыми переменными со значениями и ; выведите их произведение, преобразованное в целое число. Для вывода значений используйте метод .

Решение: 

  • Создайте веб-страницу с html-скелетом и тегом script:
<html><head><head>
<body>
<!-- Сценарий -->
<script>
	// для кода JavaScript
<script>
<!-- Конец сценария -->
<body><html>

В коде для javascript инициализируйте две строковые переменные:

var c=3.14; 
var d=0xFF; // 16-я система счисления

Вспомним, что для чисел 16-й системы используется префикс 0x. Инициализируйте две числовые переменные:

// Инициализация двух переменных:
var a="строка1"; 
var b="строка2";

Выведите результаты с помощью метода document.write() с несколькими параметрами, разделенными через запятую. Чтобы вывести в две строки следует применить тег . Для преобразования в целый тип используйте функцию parseInt():

document.write("конкатенация: ",a+b,"<br/>произведение: ", parseInt(c*d));

Протестируйте сценарий в браузере.

Задание Js 1: Даны переменные:

a="12";
b="7.15";

Найдите числовых значений переменной a на переменную b. Используйте функции преобразования типов. Результатом должно быть число 5.

Рекомендации: Для округления числа следует использовать метод :

x = Math.round(x)

Вопросы для самоконтроля:

  1. Назовите функцию, преобразующую указанную в параметре строку в целое число.
  2. Назовите функцию, преобразующую указанную строку в число с плавающей разделительной точкой.
  3. В каком случае может возникнуть ошибка NaN?
  4. Когда значение переменной может быть undefined?

JS Учебник

JS ГлавнаяJS ВведениеJS УстановкаJS ВыводJS СинтаксисJS ЗаявленияJS КомментарииJS ПеременныеJS ОператорыJS АрифметикаJS ПрисваиванияJS Типы данныхJS ФункцииJS ОбъектыJS ОбластьJS СобытияJS СтрокиJS Методы строкJS ЧислаJS Методы чиселJS МассивыJS Методы массиваJS Сортировка массиваJS Итерация массиваJS ДатыJS Формат датыJS Метод получения датJS Методы набора…JS Математические…JS Случайные числаJS БулевыJS Сравнение…JS Заявления if…elseJS Заявление switchJS Цикл forJS Цикл whileJS Заявление break…JS Преобразование…JS Битовые…JS Регулярные выраженияJS ОшибкиJS ОтладчикJS ПодъемныйJS СтрогийJS Ключевое слово thisJS Руководство стиляJS ПрактикаJS Распространенные ошибкиJS ЭффективностьJS Зарезервированные словаJS ВерсииJS Версия ES5JS Версия ES6JS JSON

alert

Это покажет в браузере всплывающее окно (попап) с текстом. (Вы можете нажать Try! и страница откроется в отдельном окне). Функция alert() сейчас используется редко, но это простой способ продемонстрировать работу JavaScript.

examples/js/alert.html

<script language="javascript">

alert("Hello World");

</script>

Try!

Если хотите попробовать сделать это самостоятельно, откройте ваш редактор и создайте файл с расширением .html (например, hello.html) и вставьте код ниже в ваш файл. Затем вернитесь в браузер и откройте файл в браузере (большиство браузеров позволяет это сделать с помощью меню File/Open File).

JS Учебник

JS ГлавнаяJS ВведениеJS УстановкаJS ВыводJS СинтаксисJS ЗаявленияJS КомментарииJS ПеременныеJS ОператорыJS АрифметикаJS ПрисваиванияJS Типы данныхJS ФункцииJS ОбъектыJS ОбластьJS СобытияJS СтрокиJS Методы строкJS ЧислаJS Методы чиселJS МассивыJS Методы массиваJS Сортировка массиваJS Итерация массиваJS ДатыJS Формат датыJS Метод получения датJS Методы набора…JS Математические…JS Случайные числаJS БулевыJS Сравнение…JS Заявления if…elseJS Заявление switchJS Цикл forJS Цикл whileJS Заявление break…JS Преобразование…JS Битовые…JS Регулярные выраженияJS ОшибкиJS ОтладчикJS ПодъемныйJS СтрогийJS Ключевое слово thisJS Руководство стиляJS ПрактикаJS Распространенные ошибкиJS ЭффективностьJS Зарезервированные словаJS ВерсииJS Версия ES5JS Версия ES6JS JSON

Тег: nodeName и tagName

Получив DOM-узел, мы можем узнать имя его тега из свойств и :

Например:

Есть ли какая-то разница между и ?

Да, она отражена в названиях свойств, но не очевидна.

  • Свойство есть только у элементов .
  • Свойство определено для любых узлов :
    • для элементов оно равно .
    • для остальных типов узлов (текст, комментарий и т.д.) оно содержит строку с типом узла.

Другими словами, свойство есть только у узлов-элементов (поскольку они происходят от класса ), а может что-то сказать о других типах узлов.

Например, сравним и на примере объекта и узла-комментария:

Если мы имеем дело только с элементами, то можно использовать или , нет разницы.

Имена тегов (кроме XHTML) всегда пишутся в верхнем регистре

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

В HTML-режиме значения всегда записаны в верхнем регистре. Будет выведено вне зависимости от того, как записан тег в HTML или .

В XML-режиме регистр сохраняется «как есть». В настоящее время XML-режим применяется редко.

innerHTML: содержимое элемента

Свойство позволяет получить HTML-содержимое элемента в виде строки.

Мы также можем изменять его. Это один из самых мощных способов менять содержимое на странице.

Пример ниже показывает содержимое , а затем полностью заменяет его:

Мы можем попробовать вставить некорректный HTML, браузер исправит наши ошибки:

Скрипты не выполнятся

Если вставляет в документ тег – он становится частью HTML, но не запускается.

Мы можем добавить HTML к элементу, используя .


Вот так:

На практике этим следует пользоваться с большой осторожностью, так как фактически происходит не добавление, а перезапись. Технически эти две строки делают одно и то же:

Технически эти две строки делают одно и то же:

Другими словами, делает следующее:

  1. Старое содержимое удаляется.
  2. На его место становится новое значение (с добавленной строкой).

Так как содержимое «обнуляется» и переписывается заново, все изображения и другие ресурсы будут перезагружены.

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

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

К счастью, есть и другие способы добавить содержимое, не использующие , которые мы изучим позже.

JS Учебник

JS ГлавнаяJS ВведениеJS УстановкаJS ВыводJS СинтаксисJS ЗаявленияJS КомментарииJS ПеременныеJS ОператорыJS АрифметикаJS ПрисваиванияJS Типы данныхJS ФункцииJS ОбъектыJS ОбластьJS СобытияJS СтрокиJS Методы строкJS ЧислаJS Методы чиселJS МассивыJS Методы массиваJS Сортировка массиваJS Итерация массиваJS ДатыJS Формат датыJS Метод получения датJS Методы набора…JS Математические…JS Случайные числаJS БулевыJS Сравнение…JS Заявления if…elseJS Заявление switchJS Цикл forJS Цикл whileJS Заявление break…JS Преобразование…JS Битовые…JS Регулярные выраженияJS ОшибкиJS ОтладчикJS ПодъемныйJS СтрогийJS Ключевое слово thisJS Руководство стиляJS ПрактикаJS Распространенные ошибкиJS ЭффективностьJS Зарезервированные словаJS ВерсииJS Версия ES5JS Версия ES6JS JSON

Классы DOM-узлов

У разных DOM-узлов могут быть разные свойства. Например, у узла, соответствующего тегу , есть свойства, связанные со ссылками, а у соответствующего тегу – свойства, связанные с полем ввода и т.д. Текстовые узлы отличаются от узлов-элементов. Но у них есть общие свойства и методы, потому что все классы DOM-узлов образуют единую иерархию.

Каждый DOM-узел принадлежит соответствующему встроенному классу.

Корнем иерархии является , от него наследует и остальные DOM-узлы.

На рисунке ниже изображены основные классы:

Существуют следующие классы:

  • – это корневой «абстрактный» класс. Объекты этого класса никогда не создаются. Он служит основой, благодаря которой все DOM-узлы поддерживают так называемые «события», о которых мы поговорим позже.
  • – также является «абстрактным» классом, и служит основой для DOM-узлов. Он обеспечивает базовую функциональность: , , и т.д. (это геттеры). Объекты класса никогда не создаются. Но есть определённые классы узлов, которые наследуют от него: – для текстовых узлов, – для узлов-элементов и более экзотический – для узлов-комментариев.
  • – это базовый класс для DOM-элементов. Он обеспечивает навигацию на уровне элементов: , и методы поиска: , . Браузер поддерживает не только HTML, но также XML и SVG. Класс Element служит базой для следующих классов: , и .
  • – является базовым классом для всех остальных HTML-элементов. От него наследуют конкретные элементы:
    • – класс для тега ,
    • – класс для тега ,
    • – класс для тега ,
    • …и т.д, каждому тегу соответствует свой класс, который предоставляет определённые свойства и методы.

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

Рассмотрим DOM-объект для тега . Он принадлежит классу .

Он получает свойства и методы из (в порядке наследования):

  • – этот класс предоставляет специфичные для элементов формы свойства,
  • – предоставляет общие для HTML-элементов методы (и геттеры/сеттеры),
  • – предоставляет типовые методы элемента,
  • – предоставляет общие свойства DOM-узлов,
  • – обеспечивает поддержку событий (поговорим о них дальше),
  • …и, наконец, он наследует от , поэтому доступны также методы «обычного объекта», такие как .

Для того, чтобы узнать имя класса DOM-узла, вспомним, что обычно у объекта есть свойство . Оно ссылается на конструктор класса, и в свойстве содержится его имя:

…Или мы можем просто привести его к :

Проверить наследование можно также при помощи :

Как видно, DOM-узлы – это обычные JavaScript объекты. Для наследования они используют классы, основанные на прототипах.

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

и

Большинство браузеров поддерживают в инструментах разработчика две команды : и . Они выводят свои аргументы в консоль. Для JavaScript-объектов эти команды обычно выводят одно и то же.

Но для DOM-элементов они работают по-разному:

  • выводит элемент в виде DOM-дерева.
  • выводит элемент в виде DOM-объекта, что удобно для анализа его свойств.

Попробуйте сами на .

Спецификация IDL

В спецификации для описания классов DOM используется не JavaScript, а специальный язык Interface description language (IDL), с которым достаточно легко разобраться.

В IDL все свойства представлены с указанием их типов. Например, , и т.д.

Небольшой отрывок IDL с комментариями:

Объясненный пример

Переменной присваивается возвращаемое значение самопроизвольной функции.

Функция самовозбуждения запускается только один раз. Она устанавливает счетчик в ноль (0) и возвращает выражение функции.

Таким образом, add становится функцией. «Замечательная» часть заключается в том, что он может получить доступ к счетчику в родительской области.

Это называется закрытием JavaScript. Это позволяет функции иметь «собственные» переменные.

Счетчик защищен областью действия анонимной функции и может быть изменен только с помощью функции .

Закрытие — это функция, имеющая доступ к родительской области, даже после закрытия родительской функции.

Блоки кода и циклы, IIFE

Предыдущие примеры сосредоточены на функциях. Но лексическое окружение существует для любых блоков кода .


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

В следующем примере переменная существует только в блоке :

Когда выполнение попадает в блок , для этого блока создаётся новое лексическое окружение.

У него есть ссылка на внешнее окружение, так что может быть найдена. Но все переменные и Function Expression, объявленные внутри , остаются в его лексическом окружении и не видны снаружи.

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

Для цикла у каждой итерации своё отдельное лексическое окружение. Если переменная объявлена в , то она также в нём:

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

И так же, как и в , ниже цикла невидима.

Мы также можем использовать «простые» блоки кода , чтобы изолировать переменные в «локальной области видимости».

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

Это может произойти, если название переменной – широко распространённое слово, а авторы скрипта не знают друг о друге.

Если мы хотим этого избежать, мы можем использовать блок кода для изоляции всего скрипта или какой-то его части:

Из-за того, что у блока есть собственное лексическое окружение, код снаружи него (или в другом скрипте) не видит переменные этого блока.

В прошлом в JavaScript не было лексического окружения на уровне блоков кода.

Так что программистам пришлось что-то придумать. И то, что они сделали, называется «immediately-invoked function expressions» (аббревиатура IIFE), что означает функцию, запускаемую сразу после объявления.

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

IIFE выглядит так:

Здесь создаётся и немедленно вызывается Function Expression. Так что код выполняется сразу же и у него есть свои локальные переменные.

Function Expression обёрнуто в скобки , потому что, когда JavaScript встречает в основном потоке кода, он воспринимает это как начало Function Declaration. Но у Function Declaration должно быть имя, так что такой код вызовет ошибку:

Даже если мы скажем: «хорошо, давайте добавим имя», – это не сработает, потому что JavaScript не позволяет вызывать Function Declaration немедленно.

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

Кроме скобок, существуют и другие пути показать JavaScript, что мы имеем в виду Function Expression:

Во всех перечисленных случаях мы объявляем Function Expression и немедленно выполняем его. Ещё раз заметим, что в настоящий момент нет необходимости писать подобный код.

Только до конца загрузки

Во время загрузки браузер читает документ и тут же строит из него DOM, по мере получения информации достраивая новые и новые узлы, и тут же отображая их. Этот процесс идёт непрерывным потоком. Вы наверняка видели это, когда заходили на сайты в качестве посетителя – браузер зачастую отображает неполный документ, добавляя его новыми узлами по мере их получения.

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

Браузер учтёт их при построении DOM, точно так же, как учитывает очередную порцию HTML-текста.

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

Текущая страница, скорее всего, уже загрузилась, поэтому если вы нажмёте на эту кнопку – её содержимое удалится:

Из-за этой особенности для загруженных документов не используют.

XHTML и

В некоторых современных браузерах при получении страницы с заголовком или включается «XML-режим» чтения документа. Метод при этом не работает.

Это лишь одна из причин, по которой XML-режим обычно не используют.

Итого

Каждый DOM-узел принадлежит определённому классу. Классы формируют иерархию. Весь набор свойств и методов является результатом наследования.

Главные свойства DOM-узла:

Свойство позволяет узнать тип DOM-узла. Его значение – числовое: для элементов, для текстовых узлов, и т.д. Только для чтения.
Для элементов это свойство возвращает название тега (записывается в верхнем регистре, за исключением XML-режима). Для узлов-неэлементов описывает, что это за узел. Только для чтения.
Внутреннее HTML-содержимое узла-элемента. Можно изменять.
Полный HTML узла-элемента. Запись в не меняет . Вместо этого она заменяет его во внешнем контексте.
Содержимое узла-неэлемента (текст, комментарий). Эти свойства практически одинаковые, обычно мы используем . Можно изменять.
Текст внутри элемента: HTML за вычетом всех . Запись в него помещает текст в элемент, при этом все специальные символы и теги интерпретируются как текст. Можно использовать для защиты от вставки произвольного HTML кода.
Когда значение установлено в , делает то же самое, что и CSS .

В зависимости от своего класса DOM-узлы имеют и другие свойства. Например у элементов () есть свойства , , у элементов () есть и т.д. Большинство стандартных HTML-атрибутов имеют соответствующие свойства DOM.

Впрочем, HTML-атрибуты и свойства DOM не всегда одинаковы, мы увидим это в следующей главе.


С этим читают