Несколько способов легко справиться с указателем this в JS

JavaScript ECMAScript 6

Автор: Дмитрий Павлютин Источник: дмитрипавлутин Переводчик: Front-end Xiaozhi

Ставь лайк и смотри, поиск в WeChat【Переезд в мир】Обратите внимание на этого человека, который не имеет большого фабричного прошлого, но имеет восходящий и позитивный настрой. эта статьяGitHub GitHub.com/QQ449245884…Он был включен, статьи были классифицированы, и многие мои документы и учебные материалы были систематизированы.

Все говорили, что нет проекта для написания резюме, поэтому я помог вам найти проект, и это было с бонусом.【Учебник по строительству】.

Мне нравится менять указатель контекста выполнения функции в JS, также известный какthisнаправление.

Например, мы можем использовать методы массива для массивоподобных объектов:

const reduce = Array.prototype.reduce;

function sumArgs() {
  return reduce.call(arguments, (sum, value) => {
    return sum += value;
  });
}

sumArgs(1, 2, 3); // => 6

с другой стороны,thisТрудно понять.

Мы часто обнаруживаем, что используемthisУказывая неправильно. Следующее научит вас, как простоthisПривязка к нужному значению.

Прежде чем начать, мне нужна вспомогательная функцияexecute(func), который выполняет только функцию, предоставленную в качестве аргумента.

function execute(func) {
  return func();
}

execute(function() { return 10 }); // => 10

Теперь продолжайте понимать окружающихthisХарактер ошибки: разделение методов.

1. Проблема разделения методов

Предположим, есть классPersonсодержит поляfirstNameа такжеlastName. Кроме того, у него есть методgetFullName(), который возвращает полное имя человека. Следующим образом:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;

  this.getFullName = function() {
    this === agent; // => true
    return `${this.firstName} ${this.lastName}`;
  }
}

const agent = new Person('前端', '小智');
agent.getFullName(); // => '前端 小智'

можно увидетьPersonФункция вызывается как конструктор:new Person('前端', '小智'). внутри функцииthisПредставляет вновь созданный экземпляр.

getfullname()Возвращает полное имя человека:'前端 小智'. как и ожидалось,getFullName()в рамках методаthisравныйagent.

Если вспомогательная функция выполняетсяagent.getFullNameЧто происходит с методом:

execute(agent.getFullName); // => 'undefined undefined'

Неверный результат выполнения:'undefined undefined',ЭтоthisУкажите на проблему, вызванную неправильным.

сейчас наgetFullName()метод,thisЗначением является глобальный объект (в среде браузераwindow).thisравныйwindow,${window.firstName} ${window.lastName}Результат выполнения есть'undefined undefined'.

Это происходит потому, что при вызовеexecute(agent.getFullName)Когда метод отсоединен от объекта. В основном происходит обычный вызов функции (не вызов метода):

execute(agent.getFullName); // => 'undefined undefined'

// 等价于:

const getFullNameSeparated = agent.getFullName;
execute(getFullNameSeparated); // => 'undefined undefined'

Это так называемый метод, отсоединенный от своего объекта, когда метод отсоединяется, а затем выполняется,thisНет связи с исходным объектом.

Чтобы убедиться, что внутреннийthisуказать на правильный объект, который должен быть выполнен

  1. Выполните метод как метод доступа к свойству:agent.getFullName()
  2. или статическиthisПривязать к содержащемуся объекту (используя стрелочные функции,.bind()метод и др.)

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

Перезвоните

// `methodHandler()`中的`this`是全局对象
setTimeout(object.handlerMethod, 1000);

При настройке обработчиков событий

// React: `methodHandler()`中的`this`是全局对象
<button onClick={object.handlerMethod}>
  Click me
</button>

Затем введите некоторые полезные методы, а именно, как сделать метод отдельным от объектаthisУкажите на нужный объект.

2. Закройте контекст

ДержатьthisСамый простой способ указать на экземпляр класса — использовать дополнительную переменнуюself:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;

  const self = this;

  this.getFullName = function() {
    self === agent; // => true
    return `${self.firstName} ${self.lastName}`;
  }
}

const agent = new Person('前端', '小智');

agent.getFullName();        // => '前端 小智'
execute(agent.getFullName); // => '前端 小智'

getFullName()статически закрытоselfПеременная, эффективноthisДелайте ручную привязку.

Теперь при звонкеexecute(agent.getFullName)когда все работает нормально, потому чтоgetFullName()в рамках методаthisвсегда указывайте правильное значение.

3. Используйте стрелочные функции

Есть ли способ статической привязки без дополнительных переменныхthis? Да, это именно то, что делают стрелочные функции.

Рефакторинг с использованием стрелочных функцийPerson:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;

  this.getFullName = () => `${this.firstName} ${this.lastName}`;
}

const agent = new Person('前端', '小智');

agent.getFullName();        // => '前端 小智'
execute(agent.getFullName); // => '前端 小智'

Стрелочные функции связаны лексическиthis. Проще говоря, он использует внешнюю функцию из своего определения.thisценность .

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

4. Привяжите контекст

Теперь давайте сделаем еще один шаг и воспользуемся рефакторингом классов в ES6.Person.

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

const agent = new Person('前端', '小智');

agent.getFullName();        // => '前端 小智'
execute(agent.getFullName); // => 'undefined undefined'

К сожалению, даже с новым синтаксисом классаexecute(agent.getFullName)все еще возвращается“undefined undefined”.

В случае классов используйте дополнительную переменнуюselfили стрелочные функции для исправленияthisуказание не работает.

Но естьbind()Трюк с методом, который связывает контекст метода с конструктором:

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    this.getFullName = this.getFullName.bind(this);
  }

  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

const agent = new Person('前端', '小智');

agent.getFullName();        // => '前端 小智'
execute(agent.getFullName); // => '前端 小智'

в конструктореthis.getFullName = this.getFullName.bind(this)методgetFullName()Привязать к экземпляру класса.

execute(agent.getFullName)Работает как положено, возвращается'前端 小智'.

5. Метод толстой стрелки

bindЭтот метод слишком многословен, мы можем использовать метод толстой стрелки:

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName = () => {
    return `${this.firstName} ${this.lastName}`;
  }
}

const agent = new Person('前端', '小智');

agent.getFullName();        // => '前端 小智'
execute(agent.getFullName); // => '前端 小智'

метод толстой стрелкиgetFullName =() =>{…}Привязывается к экземпляру класса, даже если метод отсоединен от своего объекта.

Этот метод связан в классеthisсамый эффективный и лаконичный метод.

6. Резюме

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

На уроке можно сделать用bind()для ручной привязки метода класса в конструкторе. Конечно, если вы не используетеbindЭтот многословный метод также может быть представлен лаконичной и удобной жирной стрелкой.

оригинал:GitHub.com/Валентино Г.А.…

Ошибки, которые могут существовать после развертывания кода, не могут быть известны в режиме реального времени.Чтобы решить эти ошибки впоследствии, много времени тратится на отладку журнала.Кстати, я рекомендую всем полезный инструмент мониторинга ошибок.Fundebug.

общаться с

Статья постоянно обновляется каждую неделю. Вы можете выполнить поиск «Big Move to the World» в WeChat, чтобы прочитать и обновить ее как можно скорее (на одну или две статьи раньше, чем в блоге). Эта статья находится на GitHub.GitHub.com/QQ449245884…Он был включен, и многие мои документы были разобраны. Добро пожаловать в Звезду и совершенство. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Кроме того, обратите внимание на паблик-аккаунт и ответьте в фоновом режиме.Благосостояние, вы можете увидеть преимущества, вы знаете.