В чем разница между call, apply и bind

Ответ

call, apply и bind используются для управления контекстом (this) функции, но работают по-разному:

  1. call – вызывает функцию с указанным this и аргументами, переданными по отдельности:
func.call(context, arg1, arg2, ...);
  1. apply – аналогичен call, но аргументы передаются массивом:
func.apply(context, [arg1, arg2, ...]);
  1. bind – создает новую функцию с привязанным this, но не вызывает её сразу. Аргументы можно передать при вызове:
const boundFunc = func.bind(context, arg1, arg2);
boundFunc();

Пример:

const user = { name: 'Alex' };

function greet(greeting, punctuation) {
  console.log(`${greeting}, ${this.name}${punctuation}`);
}

greet.call(user, 'Hello', '!');       // "Hello, Alex!"
greet.apply(user, ['Hi', '?']);      // "Hi, Alex?"
const boundGreet = greet.bind(user);
boundGreet('Hey', '.');              // "Hey, Alex."

Итог:

  • call/apply – вызывают функцию сразу.
  • bind – возвращает новую функцию для отложенного вызова.
  • Разница между call и apply – в способе передачи аргументов.

Ответ 18+ 🔞

Так, слушай, вот есть у нас три штуки в JavaScript — call, apply и bind. Все они, сука, про одно и то же: про то, как насильно воткнуть функции в её this то, что нам нужно, а не то, что она сама захочет. Но делают они это по-разному, эти пидоры.

Представь, что функция — это холодильник, а this — это еда внутри. Так вот эти методы — они как банда гопников, которая приходит и говорит: «Не, братан, сегодня в этом холодильнике будет не твоя пицца, а наш доширак!». И вот как они это делают:

  1. call — это такой прямолинейный гопник. Пришёл, сразу всё сделал. Говорит функции: «Работай, сука, вот твой новый this (контекст), а вот аргументы — бери их по одному, на, держи, и ещё один». И функция сразу выполняется.

    func.call(новый_this, аргумент1, аргумент2, ...);
  2. apply — это тот же гопник, но с авоськой. Суть та же, но аргументы он принёс не в руках, а сложил в один массив, типа «на, держи свою хуйню, распаковывай сам».

    func.apply(новый_this, [аргумент1, аргумент2, ...]);

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

  3. bind — а вот это уже не гопник, а хитрожопый снайпер. Он функцию не вызывает. Вместо этого он берёт её, привязывает к новому this намертво, как наручниками, и говорит: «Вот тебе новая функция, иди гуляй. А когда захочешь её вызвать — она уже будет с нашим контекстом, хоть ты тресни». Аргументы можно часть передать сразу, а часть — потом.

    const новаяФункция = func.bind(новый_this, аргумент1);
    новаяФункция(аргумент2); // Вызов потом, когда надо

Смотри, как это в жизни, на примере:

const жертва = { имя: 'Вася' };

function поздороваться(приветствие, знак) {
  console.log(`${приветствие}, ${this.имя}${знак}`);
}

// call: "Эй, функция, работай! this - жертва, аргументы - 'Привет' и '!'"
поздороваться.call(жертва, 'Привет', '!'); // Выведет: "Привет, Вася!"

// apply: То же самое, но аргументы в массиве, как будто в мешке принёс
поздороваться.apply(жертва, ['Здаров', '?']); // Выведет: "Здаров, Вася?"

// bind: Не вызываем, а создаём новую функцию, где this навсегда стал 'жертва'
const васинаФункция = поздороваться.bind(жертва);
// А вот теперь её можно хоть в таймер передать, хоть в обработчик — this не сбежит
васинаФункция('Ну чё', '...'); // Выведет: "Ну чё, Вася..."

Итог, блядь, чтобы запомнить:

  • call и apply — вызывают функцию сразу. Разница только в том, как аргументы подавать: поштучно или оптом в массиве. Выбор — дело вкуса и ситуации.
  • bind — это отложенная операция. Он создаёт новую, «забинденную» функцию, которую можно вызвать когда угодно, и this в ней уже не изменить. Пиздец как удобно для колбэков.

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