← Назад к вопросам

Как создать This?

2.0 Middle🔥 201 комментариев
#Soft Skills и рабочие процессы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как работает This в JavaScript

Это один из самых запутанных концептов. Расскажу точно как it работает.

Что такое This?

this - это ключевое слово которое ссылается на объект КОНТЕКСТА (context) где выполняется функция.

// This зависит от ТО КАК вызвана функция, а не ГДЕ она определена!
const obj = {
  name: 'Объект',
  getName: function() {
    console.log(this.name);
  }
};

obj.getName(); // this = obj -> "Объект"

const fn = obj.getName;
fn(); // this = window (или undefined в strict mode) -> undefined

1. Method Call (this = объект)

const person = {
  name: 'John',
  greet: function() {
    console.log('Привет, ' + this.name);
  }
};

person.greet(); // "Привет, John"
// this = person

2. Function Call (this = window или undefined)

function sayName() {
  console.log(this.name);
}

sayName(); // this = window (в браузере)
// В строгом режиме: this = undefined

// Strict mode
'use strict';
function sayName() {
  console.log(this); // undefined
}
sayName();

3. Constructor (this = новый объект)

function Person(name) {
  this.name = name; // this указывает на новый объект
}

const john = new Person('John');
console.log(john.name); // "John"
// this = john (новый объект)

4. Arrow Function (this из родительской области)

const obj = {
  name: 'Объект',
  
  // Обычная функция
  method1: function() {
    console.log(this.name); // "Объект"
  },
  
  // Arrow function - наследует this от родительской области
  method2: () => {
    console.log(this.name); // undefined (this = window)
  }
};

obj.method1(); // this = obj
obj.method2(); // this = window

// Arrow functions НЕ имеют своего this!

5. Явное управление This (call, apply, bind)

call() - вызвать с явным this

function greet(greeting, punctuation) {
  console.log(greeting + ', ' + this.name + punctuation);
}

const person = { name: 'John' };

greet.call(person, 'Привет', '!'); 
// this = person
// Вывод: "Привет, John!"

apply() - как call но аргументы в массиве

greet.apply(person, ['Привет', '!']);
// this = person
// Вывод: "Привет, John!"

bind() - создать новую функцию с фиксированным this

const boundGreet = greet.bind(person, 'Привет');
boundGreet('!'); // "Привет, John!"

// bind возвращает новую функцию, не вызывает её
// Это это очень важно!

Практические примеры

Пример 1: Event Handler

// ПЛОХО - this потеряется
const button = document.querySelector('button');
const component = {
  count: 0,
  increment: function() {
    this.count++; // ПЛОХО: this будет кнопка, не component!
  }
};

button.addEventListener('click', component.increment);

// ХОРОШО - используй bind
button.addEventListener('click', component.increment.bind(component));

// ХОРОШО - используй arrow function
button.addEventListener('click', () => component.increment());

Пример 2: React класс

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
    
    // ВАРИАНТ 1: bind в конструкторе
    this.increment = this.increment.bind(this);
  }
  
  // ВАРИАНТ 2: arrow function (автоматический bind)
  increment = () => {
    this.setState({ count: this.state.count + 1 });
  }
  
  // ВАРИАНТ 3: bind в JSX
  render() {
    return (
      <button onClick={this.increment}>Увеличить</button>
    );
  }
}

// ПЛОХО - this потеряется
class Counter extends React.Component {
  increment() {
    // this будет undefined
    this.setState({ count: this.state.count + 1 });
  }
  
  render() {
    return <button onClick={this.increment}>Увеличить</button>;
  }
}

Пример 3: this в методах

const obj = {
  name: 'Объект',
  
  delay: function() {
    console.log(this.name); // "Объект"
    
    // ПЛОХО - в callback this будет другой
    setTimeout(function() {
      console.log(this.name); // undefined!
    }, 1000);
  },
  
  delayFixed: function() {
    console.log(this.name); // "Объект"
    
    // ХОРОШО - arrow function сохраняет this
    setTimeout(() => {
      console.log(this.name); // "Объект"
    }, 1000);
  }
};

obj.delay(); // undefined
obj.delayFixed(); // "Объект"

Визуализация правила this

Что вызвало функцию?  |  Значение this
─────────────────────┼──────────────────────
obj.method()          |  obj
function()            |  window (или undefined)
new Constructor()     |  новый объект
arrow function        |  родительская область
fn.call(obj, ...)     |  obj (явное)
fn.apply(obj, ...)    |  obj (явное)
fn.bind(obj)          |  obj (явное, новая функция)
event.target.onclick  |  event.target

Распространённые ошибки

Ошибка 1: this в обычной функции

const user = {
  name: 'John',
  sayHi: function() {
    console.log(this.name); // "John" ✓
    
    function inner() {
      console.log(this.name); // undefined ✗
    }
    
    inner();
  }
};

// Решение - сохрани this
const user = {
  name: 'John',
  sayHi: function() {
    const self = this; // или const that = this
    
    function inner() {
      console.log(self.name); // "John" ✓
    }
    
    inner();
  }
};

// Или используй arrow function
const user = {
  name: 'John',
  sayHi: function() {
    const inner = () => {
      console.log(this.name); // "John" ✓
    };
    
    inner();
  }
};

Ошибка 2: this в setTimeout

// ПЛОХО
const obj = {
  count: 0,
  start: function() {
    setTimeout(function() {
      this.count++; // ОШИБКА: this = window
    }, 1000);
  }
};

// ХОРОШО
const obj = {
  count: 0,
  start: function() {
    setTimeout(() => {
      this.count++; // this = obj ✓
    }, 1000);
  }
};

Ошибка 3: this потеряется при деструктуризации

const obj = {
  name: 'John',
  greet: function() {
    console.log('Привет, ' + this.name);
  }
};

const { greet } = obj;
greet(); // ОШИБКА: this = undefined

// Решение
const { greet } = obj;
greet.call(obj); // ✓

// Или bind сразу
const { greet } = { ...obj };
const boundGreet = greet.bind(obj);
boundGreet(); // ✓

Дебаг this

function myFunction() {
  console.log('this =', this);
  console.log('type of this =', typeof this);
  console.log('constructor =', this.constructor.name);
}

myFunction(); // this = Window

const obj = { myFunction };
obj.myFunction(); // this = Object

const arrow = () => {
  console.log('this =', this); // наследует this из родителя
};

Чеклист

[ ] Понял я как вызвана функция?
[ ] Это метод объекта? -> this = объект
[ ] Это просто функция? -> this = window (undefined в strict)
[ ] Это конструктор? -> this = новый объект
[ ] Это arrow function? -> this из родителя
[ ] Явно передан this (call/apply/bind)? -> переданный this
[ ] Это event handler? -> this = element
[ ] Потеряется ли this в callback? -> используй arrow function

Итого

this определяется КАК вызвана функция:

  1. Method call (obj.method()) -> this = obj
  2. Function call (func()) -> this = window (undefined)
  3. Constructor (new Func()) -> this = новый объект
  4. Arrow function (() => {}) -> this из родителя
  5. call/apply/bind (func.call(obj)) -> this = obj

Практический совет:

  • В event handlers используй arrow functions
  • В классах React используй arrow functions для методов
  • Если потеряется this - используй bind или arrow function
  • Arrow functions часто спасают ситуацию!
Как создать This? | PrepBro