В «Галантерее» подробно рассказывается о различии и использовании терминов «вызвать, применить и связать».

JavaScript
В «Галантерее» подробно рассказывается о различии и использовании терминов «вызвать, применить и связать».

предисловие

предыдущий пост«Принцип и использование этой «Серии вопросов для предварительного интервью 4»В , звоните и обращайтесь.

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

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

Что общего у call и apply

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

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

То же самое верно и для изменения контекста выполнения.Объект А имеет метод, и объект Б также должен использовать тот же метод по какой-то причине.На данный момент мы должны расширить метод только для объекта Б или позаимствовать метод объекта А? Шерстяная ткань? Конечно, объект A заимствован, что не только соответствует требованиям, но и снижает использование памяти.

Кроме того, они пишутся одинаково,Объект, для которого вызываются call и apply, должен быть функцией.. Далее речь пойдет о конкретном способе написания, который и является основным проявлением их различия.

Разница между вызовом и применением

Разница между ними в основном отражается в способе записи параметров. Давайте сначала посмотрим на их конкретное письмо.

Как написать звонок

Function.call(obj,[param1[,param2[,…[,paramN]]]])

Необходимо отметить следующие моменты:

  • Объект для вызова call должен быть функцией.
  • Первым параметром вызова является объект. Вызывающий функцию укажет на этот объект. Если не передано, по умолчанию используется окно глобального объекта.
  • Начиная со второго параметра, он может принимать любое количество параметров. Каждый параметр сопоставляется с параметром функции в соответствующей позиции. Но если все параметры будут переданы в виде массива, они будут сопоставлены с первым параметром, соответствующим функции в целом, и тогда параметры будут пустыми.
function func (a,b,c) {}

func.call(obj, 1,2,3)
// func 接收到的参数实际上是 1,2,3

func.call(obj, [1,2,3])
// func 接收到的参数实际上是 [1,2,3],undefined,undefined

Как написать заявку

Function.apply(obj[,argArray])

нужно знать, это:

  • Его вызывающей стороной должна быть функция Function, и она принимает только два параметра.Правила для первого параметра такие же, как и для вызова.
  • Второй параметр, который должен быть массивом или подобным массиву, будет преобразован в массивы, подобные массиву, переданы в функцию и сопоставлены с соответствующими параметрами функции. Это также важное различие между вызовом и применением.
func.apply(obj, [1,2,3])
// func 接收到的参数实际上是 1,2,3

func.apply(obj, {
    0: 1,
    1: 2,
    2: 3,
    length: 3
})
// func 接收到的参数实际上是 1,2,3

Что такое массив классов?

Давайте сначала поговорим о массивах, с которыми мы все знакомы. Его характеристики таковы: его можно вызывать через индекс, такой как array[0]; он имеет атрибут длины length; его можно пройти через цикл for или метод forEach.

Итак, что такое массив классов? Как следует из названия, этоОбъекты с характеристиками массива. Например, следующий объект представляет собой массив классов.

let arrayLike = {
    0: 1,
    1: 2,
    2: 3,
    length: 3
};

Подобный массиву arrayLike можно вызывать через индекс, он имеет атрибут длины, а также может проходить через цикл for.

Array-like по-прежнему используется чаще, но обычно мы можем этого не замечать. Например, наш метод получения узла DOM возвращает массив классов. В другом примере все параметры, полученные с использованием аргументов в методе, также являются массивом класса.

Но следует отметить, что:Подобный массиву нельзя использовать методы в цепочке прототипов массива, такие как forEach, splice, push и т. д., в конце концов, это не массив.

Цель звонка и заявки

Некоторые сценарии использования вызова и применения перечислены ниже. Отказ от ответственности: в примере нет сцены, где нужно использовать call или apply, это просто личная привычка.

сценарии использования звонков

1. Наследование объектов. Например, следующий пример:

function superClass () {
    this.a = 1;
    this.print = function () {
        console.log(this.a);
    }
}

function subClass () {
    superClass.call(this);
    this.print();
}

subClass();
// 1

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

2. Метод заимствования. Помните массив классов только что? Если он хочет использовать методы в цепочке прототипов Array, он может сделать это:

let domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));

Таким образом, domNodes могут применять все методы в Array.

Несколько замечательных применений apply

1. Мат.макс.. Используйте его, чтобы получить самый большой элемент в массиве.

let max = Math.max.apply(null, array);

Точно так же, чтобы получить наименьший элемент в массиве, вы можете сделать это:

let min = Math.min.apply(null, array);

2. Реализовать комбинацию двух массивов. До оператора распространения ES6 мы могли сделать это с помощью Array.prototype.push.

let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];

Array.prototype.push.apply(arr1, arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]

Использование привязки

Наконец, давайте поговорим о привязке. Объяснение MDN: метод bind() создает новую функцию, которая при вызове устанавливает ключевое слово this в предоставленное значение. И когда вызывается новая функция, данный список параметров используется как несколько первых элементов последовательности параметров исходной функции.

Его синтаксис следующий:

Function.bind(thisArg[, arg1[, arg2[, ...]]])

Метод bind похож на apply и call в том смысле, что он также может изменять указатель this в теле функции. разница в том,Возвращаемое значение метода привязки — это функция, и ее необходимо вызвать позже для выполнения.. С другой стороны, apply и call вызываются немедленно.

Рассмотрим следующий пример:

function add (a, b) {
    return a + b;
}

function sub (a, b) {
    return a - b;
}

add.bind(sub, 5, 3); // 这时,并不会返回 8
add.bind(sub, 5, 3)(); // 调用后,返回 8

Если первый параметр bind имеет значение null или не определен, это относится к окну глобального объекта.

Суммировать

Основная функция вызова и применения — изменить контекст выполнения объекта и немедленно его выполнить. Они немного по другому пишутся по параметрам.

Bind также может изменить контекст выполнения объекта.В отличие от call и apply, возвращаемое значение представляет собой функцию, которую необходимо вызвать позже для выполнения.

Напоследок поделитесь удобным методом запоминания call and apply, который я видел на Жиху:

Кошки едят рыбу, собаки едят мясо, а Ультрачеловек сражается с маленькими монстрами.

Однажды собака захотела съесть рыбу

кошка ест рыбу зовет (собака, рыба)

Собака съела рыбу

Кот стал штрафом и хочет драться с монстрами

Ультрачеловек Ударь маленького монстра Звонок (кошка, маленький монстр)

Кошки тоже могут сражаться с монстрами

PS: Добро пожаловать, чтобы обратить внимание на мою общедоступную учетную запись «Super Brother Front-end Small Stack», чтобы обменяться идеями и технологиями.