Рубрики
Без рубрики

Что делать, когда «это» теряет контекст

Откройте для себя функциональный JavaScript был назван одним из лучших новых функциональных книг по программированию BookAuthority! Лучший способ избежать этого контекста потери – это вообще не использовать это. Однако это не всегда вариант. Мы можем унаследовать код, который использует это или мы можем работать с

Автор оригинала: Cristian Salcescu.

Откройте для себя функциональный JavaScript был назван одним из Лучшие новые функциональные программирования книги BookAuthority Действительно

Лучший способ избежать это Потеря контекста – не использовать это вообще. Однако это не всегда вариант. Мы можем унаследовать код, который использует это Или мы можем работать с библиотекой, использующей это Отказ

Объектные литералы, функции конструктора и Класс ES создают объекты над системой прототипы. это Pseud-Parameter используется системой прототипа для предоставления функций доступа к другим свойствам объекта.

Давайте посмотрим на некоторые ситуации.

Вложенные функции

это теряет контекст внутри вложенных функций. Рассмотрим следующий код :

class Service {
  constructor(){
    this.numbers = [1,2,3];
    this.token = "token";
  }
  
  doSomething(){
    setTimeout(function doAnotherThing(){
      this.numbers.forEach(function log(number){
      //Cannot read property 'forEach' of undefined
          console.log(number);
          console.log(this.token);
      });
    }, 100);
  }
}

let service = new Service();
service.doSomething();

dosomething () Метод имеет две вложенные функции: Doantherting () и Журнал () Отказ Когда service.dosomething () называется, это теряет контекст в вложенных функциях.

связывать()

Один из способов исправить проблему с Bind () Отказ Посмотрите на следующий код :

doSomething(){
   setTimeout(function doAnotherThing(){
      this.numbers.forEach(function log(number){
         console.log(number);
         console.log(this.token);
      }.bind(this));
    }.bind(this), 100);
  }

Bind () Создает новую версию функции, которая, когда вызывается, имеет это Значение уже установлено. Обратите внимание, что нам нужно использовать .bind (это) Для каждой вложенной функции.

Функция doantherting () {/*...*/}.bind(this) создает версию Doantherting () это берет это Значение от dosomething () Отказ

что/себя

Другой вариант – объявить и использовать новую переменную Это/я что хранит ценность это от dosomething () метод.

Смотрите код ниже :

doSomething(){
   let that = this;
   setTimeout(function doAnotherThing(){
      that.numbers.forEach(function log(number){
         console.log(number);
         console.log(that.token);
      });
    }, 100);
  }

Нам нужно объявить Пусть Во всех методах, использующих это в вложенных функциях.

Функция стрелки

Функция стрелки предлагает другой способ исправить эту проблему. Ниже приведен код :

doSomething(){
   setTimeout(() => {
     this.numbers.forEach(number => {
         console.log(number);
         console.log(this.token);
      });
    }, 100);
  }

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

Ниже тот же код С функциями выводят имя переменной:

doSomething(){    
   let log = number => {
     console.log(number);
     console.log(this.token);
   }
    
   let doAnotherThing = () => {
     this.numbers.forEach(log);
   }
    
   setTimeout(doAnotherThing, 100);
}

Метод как обратный вызов

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

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

class Service {
  constructor(){
    this.token = "token"; 
  }
  
  doSomething(){
    console.log(this.token);//undefined
  } 
}
let service = new Service();

Теперь давайте посмотрим на некоторые ситуации, где метод service.dosomething () используется в качестве обратного вызова.

//callback on DOM event
$("#btn").click(service.doSomething);

//callback for timer
setTimeout(service.doSomething, 0);

//callback for custom function
run(service.doSomething);

function run(fn){
  fn();
}

Во всех предыдущих ситуациях это теряет контекст.

связывать()

Мы можем использовать Bind () решить проблему. Проверьте следующий кодовый фрагмент :

//callback on DOM event
$("#btn").click(service.doSomething.bind(service));

//callback for timer
setTimeout(service.doSomething.bind(service), 0);

//callback for custom function
run(service.doSomething.bind(service));

Функция стрелки

Другой вариант – создать новую функцию, которая звонит service.dosomething () Отказ

//callback on DOM event
$("#btn").click(() => service.doSomething());

//callback for timer
setTimeout(() => service.doSomething(), 0);

//callback for custom function
run(() => service.doSomething());

Реагистрационные компоненты

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

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

class TodoAddForm extends React.Component {
  constructor(){
      super();
      this.todos = [];
  }
  
  componentWillMount() {
    this.setState({desc: ""});
  }
  
  add(){
    let todo = {desc: this.state.desc}; 
    //Cannot read property 'state' of undefined
    this.todos.push(todo);
  }
  
  handleChange(event) {
     //Cannot read property 'setState' of undefined
     this.setState({desc: event.target.value});
  }
  
  render() {
    return 
; } } ReactDOM.render( , document.getElementById('root'));

Способ исправления проблемы состоит в том, чтобы создать новые функции в конструкторе, используя Свяжитесь (это) Отказ

constructor(){
   super();
   this.todos = [];
   this.handleChange = this.handleChange.bind(this);
   this.add = this.add.bind(this);
}

Не используя “это”

Нет это Без проблем с потерей контекста. Объекты могут быть созданы с использованием заводских функций. Проверьте этот код :

function Service() {  
  let numbers = [1,2,3];
  let token = "token";
  
  function doSomething(){
   setTimeout(function doAnotherThing(){
     numbers.forEach(function log(number){
        console.log(number);
        console.log(token);
      });
    }, 100);
  }
  
  return Object.freeze({
    doSomething
  });
}

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

let service = Service();
service.doSomething();

//callback on DOM event
$("#btn").click(service.doSomething);

//callback for timer
setTimeout(service.doSomething, 0);

//callback for custom function
run(service.doSomething);

Заключение

это может потерять контекст в разных ситуациях.

Bind () Этот/самостоятельный шаблон и функции стрелки являются инструментами в нашем распоряжении для решения проблем контекста.

Функции завода дают возможность создавать объекты без использования это вообще.

Откройте для себя функциональный JavaScript был назван одним из Лучшие новые функциональные программирования книги BookAuthority Действительно

Для получения дополнительной информации о применении методов функциональных программиров в реакции посмотрите на Функциональный реагировать Отказ

Учить Функциональный реагировать в проекте, основанном на проекте, с Функциональная архитектура с реагированием и redux Отказ

Следуйте в Twitter

Оригинал: “https://www.freecodecamp.org/news/what-to-do-when-this-loses-context-f09664af076f/”