Что означает «javascript:void(0)»?

How to Enable Javascript on Internet Explorer?

Step 1 – Open Internet Explorer on your computer after ensuring your user account has administrator permissions.Step 2 – Select the “Tools” menu option from the Internet Explorer “Task Bar.”Step 3 – Choose the “Security” and “Custom Level” menu options.

Step 4 – Locate the “Scripting” section of the subsequently displayed menu.

Step 5 – Click the “Enable” radio button located next to the “Active Scripting” and “Allow Programmatic clipboard access” menu options.

Step 6 – Select the “OK” menu button.

Step 7 – Restart Internet Explorer to complete enabling Javascript on the target computer.

Элементы, связанные с событием

Чаще всего нужно узнать, на каком элементе сработало событие.

Например, мы поймали на внешнем ‘е и хотим знать, на каком из внутренних элементов оно на самом деле произошло.

В Internet Explorer у объекта для этого есть свойство , в остальных браузерах, работающих по рекомендациям W3C, для этого используется .

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

1

2
3
Ссылка

<div class="d1" 
  onclick="*!*t=event.target||event.srcElement; alert(t.className)*/!*"
>
<span class="number">1</span>
    <div class="d2">
        <span class="number">2</span>
        <div class="d3">
            <span class="number">3</span>
        </div>
        <a class="d2a" href="javascript:void(0)">Ссылка</a>
    </div>
</div>

Javascript-обработчик в примере висит только на внешнем диве и выглядит примерно так:

function(event) {
  // получить объект событие.
  // вместо event лучше писать window.event
  event = event || window.event

  // кросс-браузерно получить target
  var t = event.target || event.srcElement

  alert(t.className)
}

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

Эти свойства — в W3C, и в Internet Explorer.

// Обработчик для mouseover
function mouseoverHandler(event) {
	event = event || window.event
	var relatedTarget = event.relatedTarget || event.fromElement
	// для mouseover
	// relatedTarget - элемент, *!*с которого*/!* пришел курсор мыши
}

// Обработчик для mouseout
function mouseoutHandler(event) {
	event = event || window.event
	var relTarg = event.relatedTarget || event.toElement
	// для mouseout
	// relatedTarget - элемент, *!*на который*/!* перешел курсор мыши
}

Свойство дополняет . В нем всегда находится информация о втором элементе, участвовавшем в событии.

Поэтому его можно получить для IE, взяв то свойство из , которое не равно :

if (!e.relatedTarget && e.fromElement) {
  e.relatedTarget = (e.fromElement==e.target) ? e.toElement : e.fromElement
}

При всплытии — событие по очереди вызвает обработчики на элементе-триггере и дальше, вверх по документу.

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

Стандартный способ получить текущий элемент — использовать переменную .

Например, при клике на внутренний , код в этом примере последовательно отмечает элементы, на которых регистрируется всплывающее событие:

1

2

3

<div class="d1" onclick="highlightMe(this)">1
    <div class="d2" onclick="highlightMe(this)">2
        <div class="d3" onclick="highlightMe(this)">3</div>
    </div>
</div>

Conflicts with Anti-Popup Software

Although commonly embedded within web browsers and other computer security software today, there are still a number of consumers who download and use anti-popup software. These applications are created in order to eliminate the pop-up windows that launch on visiting some websites. Although pop-up blockers prove beneficial to many end-users, they can cause issues on websites one is trying to view. This results from many of the pop-up blocking technologies  on the market achieving their desired effect by shutting down the Javascript embedded on the targeted webpage. A secondary effect to blocking the pop-up is that the javascript:void(0) error can be thrown if the desired webpage relies on Javascript to work properly.
A short-term solution is to turn off your pop-up blocking program. Then, if you want to keep using the application you need to validate the configuration settings for the application. Many of the popular pop-up blocking programs will provide options that allow Javascript to run on the targeted website so you don’t remove all functionality while also avoiding the javascript:void(0) error.

The typeof Operator

The typeof operator returns the type of a variable, object, function or
expression:

Example

typeof «John»                
// Returns string
typeof 3.14                  
// Returns number
typeof NaN                   
// Returns number
typeof false                 
// Returns boolean
typeof            // Returns object
typeof {name:’John’, age:34} 
// Returns objecttypeof new Date()            
// Returns objecttypeof function () {}         // Returns function
typeof myCar                 
// Returns undefined (if myCar is not declared)
typeof null                  
// Returns object

Please observe:

  • The data type of NaN is number
  • The data type of an array is object
  • The data type of a date is object
  • The data type of null is object
  • The data type of an undefined variable is undefined

You cannot use typeof to define if a JavaScript object is an
array (or a date).

7) addClass() / removeClass()

Следующие две функции добавляют и удаляют класс DOM элемента.

function addClass(o, c){
    var re = new RegExp("(^|\\s)" + c + "(\\s|$)", "g")
    if (re.test(o.className)) return
    o.className = (o.className + " " + c).replace(/\s+/g, " ").replace(/(^ | $)/g, "")
}
 
function removeClass(o, c){
    var re = new RegExp("(^|\\s)" + c + "(\\s|$)", "g")
    o.className = o.className.replace(re, "$1").replace(/\s+/g, " ").replace(/(^ | $)/g, "")
}

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

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

function toggle(el) {
    el.style.display = (el.style.display == 'none') ? '' : 'none'
}

Обратите внимание, в функции нет ни слова про , вместо этого используется пустое значение. Пустое значение означает сброс свойства, т.е

свойство возвращается к значению, указанному в CSS.

Таким образом, если значение для данного элемента, взятое из CSS — (элемент спрятан по умолчанию), то эта функция не будет работать.

Этот вариант функции красив и прост, однако этот и некоторые другие недостатки делают его недостаточно универсальным. Более правильный вариант , а также функции и описаны в статье Правильные show/hide/toggle.

Тег: nodeName и tagName

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

Например:

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

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

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

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

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

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

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

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

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

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

Пример ошибочного использования

Функция принимает массив ‘ов и ставит каждому вывод своего номера на .

С вопроса «Почему это не работает?» люди обычно начинают изучение замыканий.

function addEvents(divs) {
	for(var i=0; i<divs.length; i++) {	
		divs.innerHTML = i
		divs.onclick = function() { alert(i) }
	}
}

Для тестового примера сделаем 10 разноцветных нумерованных ‘ов с разными цветами:

function makeDivs(parentId) {
	for (var i=0;i<10;i++) {
		var j = 9-i
		var div = document.createElement('div')
		div.style.backgroundColor = '#'+i+i+j+j+j+i
		div.className="closure-div"
		div.style.color = '#'+j+j+i+i+i+j
		document.getElementById(parentId).appendChild(div)
	}
}

Кнопка ниже создаст 10 дивов и вызовет для них

Если Вы покликаете на div’ы — они все выдают одинаковый alert.

Такой глюк возник из-за того, что все функции получают значение из одного на всех внешней функции. А это значение () на момент активации -обработчика равно 10 (цикл завершился как только ).

Чтобы все было в порядке, в таких случаях применяют специальный прием — выделение . Следующая функция работает правильно. В ней все то же самое, кроме .

function addEvents2(divs) {
	for(var i=0; i<divs.length; i++) {	
		divs.innerHTML = i
		divs.onclick = function(x) {
			return function() { alert(x) }
		}(i)
	}
}

Теперь все должно быть в порядке — каждый дает на свой номер.

Для присваивания запускается временная функция , принимающая аргумент и возвращающая обработчик, который берет из этой временной функции.

Запись используется для создания функции, и тут же — для запуска с аргументом .

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

var f = function(a) { return  }
var t = f(1)
var result = t // 2

можно в одну строчку создать и тут же вызвать функцию и тут же получить 2й элемент массива:

var result = function(a){ return  }(1)

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

Когда обработчик активизируется — возьмет из ближайшей внешней функциии правильное значение .

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

Также про замыкания можно почитать, например в cтатье http://www.jibbering.com/faq/faq_notes/closures.html

3, 2 и 1) getCookie(), setCookie(), deleteCookie()

В javascript нет способа нормально работать с cookie без дополнительных функций. Не знаю, кто проектировал , но сделано на редкость убого.

Поэтому следующие функции или их аналоги просто необходимы.

// возвращает cookie если есть или undefined
function getCookie(name) {
	var matches = document.cookie.match(new RegExp(
	  "(?:^|; )" + name.replace(/(\\\/\+^])/g, '\\$1') + "=(*)"
	))
	return matches ? decodeURIComponent(matches) : undefined 
}

// уcтанавливает cookie
function setCookie(name, value, props) {
	props = props || {}
	var exp = props.expires
	if (typeof exp == "number" && exp) {
		var d = new Date()
		d.setTime(d.getTime() + exp*1000)
		exp = props.expires = d
	}
	if(exp && exp.toUTCString) { props.expires = exp.toUTCString() }

	value = encodeURIComponent(value)
	var updatedCookie = name + "=" + value
	for(var propName in props){
		updatedCookie += "; " + propName
		var propValue = props
		if(propValue !== true){ updatedCookie += "=" + propValue }
	}
	document.cookie = updatedCookie

}

// удаляет cookie
function deleteCookie(name) {
	setCookie(name, null, { expires: -1 })
}

Аргументы:

name
название cookie
value
значение cookie (строка)
props
Объект с дополнительными свойствами для установки cookie:

expires
Время истечения cookie. Интерпретируется по-разному, в зависимости от типа:

  • Если число — количество секунд до истечения.
  • Если объект типа Date — точная дата истечения.
  • Если expires в прошлом, то cookie будет удалено.
  • Если expires отсутствует или равно 0, то cookie будет установлено как сессионное и исчезнет при закрытии браузера.
path
Путь для cookie.
domain
Домен для cookie.
secure
Пересылать cookie только по защищенному соединению.

Подробное описание

.. Если Вы хотите углубиться поглубже и разбираться подольше..

..На самом деле происходящее в интерпретаторе Javascript гораздо сложнее и содержит куда больше деталей, чем здесь описано…

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

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

Каждый вызов … — всего лишь создает новое свойство этого объекта, а любое упоминание переменной — первым делом ищется в свойствах этого объекта.

Такова внутренняя структура «области видимости» — это обыкновенный объект. Все изменения локальных переменных являются изменениями свойств этого неявного объекта.

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

Общий поток выполнения выглядит так:

// функция для примера
function sum(x,y) {
	// неявно создался объект `scope`
	...
	// в `scope` записалось свойство z
	var z
	// нашли переменную в `scope`, `scope`.z = x+y
	z = x+y
	// нашли переменную в `scope`, return `scope`.z
	return z

	// функция закончилась,
	// `scope` никому больше не нужен и умирает вместе с z
}

Кстати, для кода вне функции(и вообще глобальных переменных) роль объекта-контейнера выполняет объект .

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

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

Например, разберем работу функции, которая устанавливает обработчики событий:

function addHideHandler(sourceId, targetId) {
	// создан объект `scope` со свойствами sourceId, targetId

	// записать в `scope` свойство sourceNode
	var sourceNode = document.getElementById(sourceId)

	// записать в `scope` свойство handler
	var handler = function() {
		var targetNode = document.getElementById(targetId)
		targetNode.style.display = ‘none’
	}

	sourceNode.onclick = handler

	// функция закончила выполнение
	// (***) и тут - самое интересное!
}

При запуске функции все происходит стандартно:

  1. создается
  2. туда записываются локальные переменные
  3. внутренняя функция получает ссылку на

Но в самом конце — внутренняя функция присваивается . Внешняя функция закончила свою работу, но внутренняя — может запуститься когда-нибудь потом.

Интерпретатор javascript не проводит анализ — понадобятся ли внутренней функции переменные из внешней, и какие переменные могут быть нужны.

Вместо этого он просто оставляет весь внешней функции в живых.

Чтобы когда внутренняя функция запустится, если она вдруг не найдет какую-либо переменную в своем — она могла обратиться к внешней функции и нашла бы ее там.

Если внешняя функция была создана внутри еще одной (еще более внешней) функции — то в цепочку добавляется еще один консервированный и так — до глобальной области .

В каких задачах используется void?

На сегодняшний день данный механизм можно использовать в трех направлениях:

  • Вместо значения undefined;
  • Для создания букмарклетов;
  • Для ссылок, которые выполняют некий js-код.

Разберем каждый из вариантов отдельно.

Замена стандартного значения выражением void (0)

Данная команда обладает одним преимуществом, поэтому так часто используется в некоторых проектах: ее значение нельзя переопределить, в то время как undefined может быть не только переопределено, а еще и затерто по ходу выполнения команд в коде.

В подтверждение этого я прикрепил небольшое приложение.

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html> 
<html> 
<head> 
<meta charset="utf-8" /> 
<title>undefined</title> 
<script type="text/javascript"> 
function sayHi(undefined) { return undefined; }
</script> 
</head> 
<body> 
<p><a href="javascript:sayHi('hello')">Поприветствуй пользователя, нажми на ссылку. </a></p> 
</body> 
</html>

В результате в диалоговое оно будет выведено слово «hello». Это несмотря на то, что возвращался другой параметр.

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

cd45c6d133599f1a0fc4ef4bc95f19cd001

Изменилось всего лишь возвращаемое значение функцией, однако веб-страница не перегружается. Если же попытаться переопределить оператор — var void = undefined или var void = ‘hi!’ – то появится сообщение об ошибке.

Букмарклеты

Для его оформления используется протокол

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

Так, при запуске этого примера контент на текущей странице обновится:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html> 
<html> 
<head> 
<meta charset="utf-8" /> 
<title>undefined</title> 
<script type="text/javascript"> 
function sayHi(undefined) { return void(0); }
</script> 
</head> 
<body> 
<p><a href="javascript:sayHi('hello')">Поприветствуй пользователя, нажми на ссылку. </a></p> 
</body> 
</html>

Чтобы это запретить, нужно перед свойством window.location.href дописать операцию void.

Есть и альтернативное решение – открыть ссылку в новой вкладке. Это реализовывается строкой:

Ссылки, которые выполняют js-код

Очень редко, однако все-таки иногда встречаются программы, в которых анкоры, которые внедрили в веб-приложения, запускают js-функцию. Проблем не возникает, если функция возвращает void.

Однако если же после вызова функции она возвращает какое-то значение, стоит принять меры для предотвращения изменения контента веб-страницы. И опять-таки можно воспользоваться оператором void.

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

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

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

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

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

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

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

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

Вот так:

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

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

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

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

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

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

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

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

Problems with Internet Proxies

Internet proxy servers function as an intermediary between end-users and websites. Since they help create a layer of anonymity between end-users and website, they are highly popular. Unfortunately, they can also interfere with the loading of Javascript on websites an end-user is surfing. Of course, the easiest way to avoid the issue is to just not use a proxy. For many individuals; however, this is either 1 – not possible, or 2 – not preferred. As a result, if you are getting the Javascript:void(0) error while using a proxy, one should locate a different proxy server and attempt the same task. If the error persists, then attempt to find a proxy server which uses a different script than the one you are trying to use.

The in Operator

The in operator returns true if the specified property is in the specified object,
otherwise false:

Example

// Arraysvar cars = ;»Saab» in cars          // Returns false (specify the index number instead of value)0 in cars               // Returns true1 in cars               // Returns true4 in cars               // Returns false (does not exist)»length» in cars        // Returns true  (length is an Array property)// Objects
var person = {firstName:»John», lastName:»Doe», age:50};»firstName» in person   // Returns true»age» in person         // Returns true// Predefined objects»PI» in Math            // Returns true»NaN» in Number         // Returns true»length» in String      // Returns true

What is Javascript?

Javascript is an interpreted programming language that has been embedded in web browsers for a number of years. It is formally defined in the ECMAScript language standard and primarily is deployed in web browsers.  The language allows client-side scripts to be embedded within webpages to help the end-user interact with websites, control the browser, dynamically alter content, and is very common in game and desktop application development. The language is type-safe, dynamic is was significantly influenced by the C programming language. There are a number of naming conventions copied from the Java programming language; however, that is where the similarity with Java stops.

Modern Javascript is based on the Scheme and Self programming languages and support object orientated, functional, and imperative programming styles in implementation. Use of the language has grown to include desktop widgets, PDF documents, and site-specific browsers today. There have also been a number of Javascript frameworks released which feature faster performance that have aided in the popularity of the script on the server-side for Internet applications. Due to the increased popularity of the language, the number of locations that an end-user can run into the javascript:void(0) error has significantly increased over the past decade.

Классы 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 с комментариями:

outerHTML: HTML элемента целиком

Свойство содержит HTML элемента целиком. Это как плюс сам элемент.

Посмотрим на пример:

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

Да, звучит странно, и это действительно необычно, поэтому здесь мы и отмечаем это особо.

Рассмотрим пример:

Какая-то магия, да?

В строке мы заменили на . Во внешнем документе мы видим новое содержимое вместо . Но, как видно в строке (), старая переменная осталась прежней!

Это потому, что использование не изменяет DOM-элемент, а удаляет его из внешнего контекста и вставляет вместо него новый HTML-код.

То есть, при произошло следующее:

  • был удалён из документа.
  • Вместо него был вставлен другой HTML .
  • В осталось старое значение. Новый HTML не сохранён ни в какой переменной.

Здесь легко сделать ошибку: заменить , а потом продолжить работать с , как будто там новое содержимое. Но это не так. Подобное верно для , но не для .

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector