ECMAScript LanguageSpecification

<p id="element" onclick="doSomething();">Click me</p>

, потому что его легче отлаживать.

Однако я слышу, как люди говорят, что не следует использовать встроенный js, и делаю:

document.getElementById('element').onclick = doSomething;

Почему рекомендуется прослушивать события js?

В основном это связано с тем, что все держится отдельно. Так что держите HTML / CSS / JS отдельно. Это делает ваш HTML более аккуратным и, я думаю, легче ориентироваться без него.

Тогда, когда / если вам нужно внести большие изменения, у вас будет достаточно места для того, чтобы все равно переместить встроенный JS во внешний файл ИЛИ, если вы хотите применить одну и ту же функцию к более чем одной кнопке, тогда кода будет меньше. И чем меньше кода, тем лучше.

Если у вас есть правильные и тщательно документированные JS-файлы, то навигация по ним со стороны постороннего становится делом eaiser

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

. Однако на самом деле есть более серьезная проблема IMO: каким-то неуловимым способом встроенного обработчики событий оцениваются.

Как вы, возможно, знаете, содержимое атрибутов on* будет использоваться как тело функции-обработчика события. Но какими характеристиками обладает эта функция?

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

<form>
    <input name="foo" />
    <button type="button" onclick="console.log(foo); console.log(window.foo);">
        Click me
    </button>
    <div onclick="console.log(foo);">Click me as well!</div>
</form>

кликах button logs

<input name="foo"></input>
undefined

в консоли. Тот факт, что window.foo, undefined сообщает, что нет глобальной переменной foo. Так откуда берется переменная foo? Почему console.log(foo) регистрирует элемент ввода и не выдает ошибку ссылки?
Поскольку свойства элемента form в области действия обработчика события и form имеют свойство для каждого именованного элемента управления формы, которое он содержит. Вы можете легко проверить это с помощью console.log(document.querySelector('form').foo) Глядя на вывод

Теперь, щелкнув элемент div, выдается ошибка ссылки:

ReferenceError: foo is not defined

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

Аналогичным образом, свойства объекта document также находятся в области действия встроенных обработчиков событий, что может привести к некоторым неожиданным ошибкам (вы знали это document имеет свойство plugins?).

Как именно оцениваются встроенные обработчики событий, формализовано в спецификации HTML5 . Создайте цикл на шаге 10, в частности, где описано создание цепочки областей действия.


Заключение :

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

Статьи на quirksmode.org не является стандартным. Вам нужно создать событие и отправить его:

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

Быстрый пример (я использую jQuery просто для демонстрационных целей).

<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>

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

<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>

$('.element').bind('click', doSomethingElse);

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

Мы только что выпустили Приведу пример для моего комментария ниже.

Project = {
    // All the variables/constants/objects that need to be globally accessible inside the Project object.

    init : function(){
        // Main entry point...
        this.MainMenu.init();

        // Rest of the code which should execute the moment Project is initiated.
    }
}

Project.MainMenu = {
    // All the variables/constants/objects that need to be accessible only to MainMenu.

    init : function(){ // Is run immediatelly by Project.init()
        // Event handlers relevant to the main menu are bound here

        // Rest of the initialization code
    }
}

Project.SlideShow = {
    // All the variables/constants/objects that need to be accessible only to SlideShow.

    init : function(){ // Is run only on pages that really require it.
        // Event handlers for the slideshow.
    }
}

Несмотря на то, что могут подумать другие люди, я думаю, что есть полезная ценность для включения слушателей в разметку. В частности, это дает вам гораздо больше свободы для изменения узлов DOM. Если вы добавляете слушателей через JavaScript, слушатели теряются при замене innerHTML любых родительских узлов. Если вы встраиваете слушателей в разметку, вы можете клонировать узел, внести в него изменения, а затем заменить исходный узел тем узлом, который вы только что клонировали и изменили.

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

Я вижу некоторые высказывания о необходимости разделения интересов в отношении презентаций и бизнес-логики.

ОП в его примере действительно показывает это разделение! В встроенном обработчике событий нет логики, а просто ссылка на функцию / вызов, которая будет выполняться при событии «click» … сама логика может поддерживаться отдельно в другом месте.

Я лично предпочитаю этот подход из-за логического обнаружения потока. Если я никогда раньше не видел приложения … первое место, где я собираюсь начать свой обход кода, находится в DOM, и тут же станет ясно, какие обработчики событий находятся в игре, а какие функции обеспечивают логику для обработчики. С использованием, скажем, подхода к обработке событий «JQuery.On», просто просматривая html, вы не представляете, какие обработчики на самом деле подключены и предоставляют функциональность.

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

Вы можете сказать то же самое о CSS и включении встроенных стилей. Было бы легко не просматривать файл css, чтобы найти текущий класс / id или родительские / дочерние элементы, с которыми вы работаете.

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

Помимо перспективы стандартов кодирования

Использование атрибутов:

<p id="element" onclick="doSomething();">Click me</p>

, если вы снова добавляете тот же атрибут (см. Ниже), рассматривается последний.

<p id="element" onclick="doSomethingMore();">Click me</p>

Использование обработчика событий:

document.getElementById('element').onclick = doSomething;

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

document.getElementById('element').onclick = doSomethingMore; Вызываются оба обработчика.

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

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