Разный контекст при разном навешивании обработчика событий

Рейтинг: 2Ответов: 3Опубликовано: 14.08.2023

Почему обработка события через JS работает как надо, а через html, this ссылается на window Есть такая функция

function foo() {
  console.log(this)
}

В этом примере работает нормально

let btn = document.querySelector('button');
btn.onclick = foo;

Здесь ссылается на window

<button onclick="foo()">Button</button>

Причем так тоже работает нормально

<button onclick="console.log(this)">Button</button>

Ответы

▲ 0Принят

this - контекст вызова функции, если кратко, то содержимое фигурных скобок {} выше тела функции.

Теперь посмотрим что получается у вас:

function foo() {
  console.log(this)
}

Если просто вызвать foo() то вы увидите window, так функция объявлена, по сути, в глобальной области видимости или в window

Если сделать так:

const newContext = {
  fn: foo
}
newContext.fn();

то вы увидите объект newContext

А теперь посмотрим на регистрацию событий нажатия кнопки(click):

<button onclick="foo()">Button1</button> 

Тут this берется из окружения, где объявлена функция(здесь она будет только вызываться)
А вот здесь:

let btn = document.getElementById("btn");
btn.onclick = foo;

this это объект btn - по аналогии с newContext


Если вам очень хочется указывать обработчик события из HTML, то можно сделать так:

function foo2(self) {
    console.log(self)
}
<button>Button</button>

▲ 0

Ознакомьтесь с this и областью видимости. this — это уникальная переменная, которая хранит в себе контекст исполняемого кода. Контекст this меняется в зависимости от его использования.

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

function foo() {
  console.log('Что-то')
}
<button onclick="foo()">Button</button>

Статья на habr по this - советую ознакомиться, удачи !)

▲ 0

Потому что текст обработчика - это код функции, которая вызывается с неким this.

console.log(document.querySelector('button').onclick)
<button>Button</button>

Когда ты пишешь вызов функции, это всего лишь стейтемент в коде другой функции, а вызов foo(), очевидно, происходит с контекстом window или undefined.

console.log(document.querySelector('button').onclick)
<script>function foo() { console.log(this === window) }</script>
<button>Button</button>

Когда ты присваиваешь функцию в коде, ты присваиваешь саму функцию, а не создаёшь тело функции:

const btn = document.querySelector('button')
btn.onclick = foo
console.log(btn.onclick)
<script>function foo() { console.log(this === window || this) }</script>
<button>Button</button>