Почему Activity, Service, BroadcastReceiver и ContentProvider считаются основными компонентами

Ответ

Ответ не найден

Ответ 18+ 🔞

А, ну это ж классика, блядь! Ты знаешь, когда я впервые с этим столкнулся, я сам от себя охуел. Сижу такой, кодирую, всё по фен-шую, а тут — на тебе! Ёперный театр, просто пиздец.

В общем, слушай сюда. Есть у нас в JavaScript такая штука — this. И вот эта мудя, она ведёт себя не как нормальная переменная, а как хитрая жопа. Контекст её зависит не от того, где её объявили, а от того, как её ВЫЗВАЛИ. Представляешь? Подозрение ебать чувствую к такой логике.

Вот смотри, самый простой пример, от которого волосы дыбом встают.

const user = {
  name: 'Вася',
  greet() {
    console.log(`Привет, я ${this.name}`);
  }
};

const greetFunc = user.greet; // Вытащили метод отдельно
greetFunc(); // Выводит: "Привет, я undefined"

Вот тут-то и начинается веселье, ёпта. Мы думаем: «Ну метод же у объекта, имя есть, чё не так?» А не так всё, блядь! Когда мы присвоили user.greet переменной greetFunc, мы оторвали функцию от её контекста. И теперь, когда вызываем просто greetFunc(), this внутри неё смотрит уже не на объект user, а в глобальную область видимости (или становится undefined в строгом режиме). И name там, естественно, нет. Вот тебе и доверия ебать ноль.

А теперь представь, что ты передаёшь этот метод как колбэк, например, в setTimeout. Это вообще отдельная история, хуй с горы.

setTimeout(user.greet, 1000); // Через секунду: "Привет, я undefined"

Всё по той же причине. Функция user.greet передаётся, а контекст user — нет. Овердохуища неожиданностей для новичков, я тебе скажу.

Так как же с этим бороться, спросишь ты? Ну, способов — вагон и маленькая тележка. Самый простой и тупой — привязать контекст намертво.

Способ 1: bind — привяжи и забудь. Это как дать функции пожизненный контекст. Хуй в пальто, но работает.

const boundGreet = user.greet.bind(user); // Намертво привязали `this` к `user`
setTimeout(boundGreet, 1000); // Теперь выведет: "Привет, я Вася"
const anotherFunc = boundGreet;
anotherFunc(); // И это тоже: "Привет, я Вася"

Способ 2: Стрелочные функции — спасение наше. Вот это уже красота, блядь. У стрелочных функций (=>) нет своего this. Они берут его из окружающей лексической области. То есть, как у нормальных людей, а не как у этой манды с ушами — обычного function.

const user = {
  name: 'Вася',
  greet: function() {
    // Обычная функция, тут свой this
    setTimeout(() => {
      // А тут стрелочная, она ВЗЯЛА this из greet
      console.log(`Привет (через секунду), я ${this.name}`);
    }, 1000);
  }
};

user.greet(); // Выведет: "Привет (через секунду), я Вася"

Видишь магию? Внутренняя стрелочная функция просто схавала this из внешней функции greet, где он как раз указывает на user. Удобно, ёб твою мать!

Способ 3: Классика жанра — call и apply. Эти ребята не создают новую функцию, а сразу вызывают старую, но с указанным тобой контекстом. Разница лишь в том, как аргументы передавать.

function introduce(age, city) {
  console.log(`Меня зовут ${this.name}, мне ${age}, из ${city}`);
}

const person = { name: 'Петя' };

// call — аргументы через запятую
introduce.call(person, 30, 'Москва'); // Меня зовут Петя, мне 30, из Москва

// apply — аргументы массивом
introduce.apply(person, [30, 'Москва']); // Тот же результат

В общем, чувак, суть в чём: this в JavaScript — это не значение, а контекст вызова. Пока ты это не прочувствуешь кожей, будешь постоянно наступать на эти грабли. Но как только въедешь — всё становится на свои места. Главное — не паниковать, когда в очередной раз увидишь undefined вместо имени. Просто вспомни: «А, точно, контекст потерял, полупидор». И лечи это bind'ом или стрелочной функцией.