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

Как понять ключевое слово это и контекст в JavaScript

Лукас Гисдер-Дубко Как понять ключевое слово это и контекст в JavaScriptPhoto beasty. На Unsplashas упоминается в одном из моих предыдущих статей, освоение JavaScript полностью может быть длительным путешествием. Возможно, вы нашли это в вашем путешествии как разработчик JavaScript. Когда я начал, I

Автор оригинала: FreeCodeCamp Community Member.

Лукас Гисдер-Дуб

Как упоминалось в Один из моих предыдущих статей Овладение JavaScript полностью может быть длительным путешествием. Возможно, вы нашли это В вашем путешествии как разработчик JavaScript. Когда я начал, я впервые увидел это при использовании EventListeners и с jQuery. Позже я должен был использовать его часто с реагированием, и я уверен, что вы также сделали. Это не значит, что я действительно понял, что это такое и как полностью контролировать его.

Тем не менее, очень полезно освоить концепцию позади этого, и при приближении к чистому уму тоже не очень сложно.

Копаться в этом

это Плотно связан с каким контекстом, в вашей программе. Давайте начнем весь путь наверху. В нашем браузере, если вы просто введите это В консоли вы получите окно -объект, внешний контекст для вашего JavaScript. В Node.js, если мы сделаем:

console.log(this)

Мы в конечном итоге с {} пустой объект. Это немного странно, но кажется, что Node.js ведет себя таким образом. Если вы сделаете

(function() {
  console.log(this);
})();

Тем не менее, вы получите глобальный объект, внешний контекст. В этом контексте Сетримс С Setinterval , хранятся. Не стесняйтесь играть немного, чтобы увидеть, что вы можете сделать с этим. Как отсюда, между Node.js практически нет никакой разницы между Node.js и браузером. Я буду пользоваться окно Отказ Просто помните, что в Node.js это будет глобальный Объект, но это на самом деле не имеет значения.

Помните: контекст имеет смысл только внутри функций

Представьте, что вы пишете программу, не вложенное в функции. Вы бы просто написали одну строку за другой, не спустившись с определенными структурами. Это означает, что вам не нужно отслеживать, где вы находитесь. Вы всегда на одном уровне.

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

Отслеживание объекта вызывающего абонента

Давайте посмотрим на следующий пример и посмотрите, как это изменения в зависимости от контекста:

const coffee = {
  strong: true,
  info: function() {
    console.log(`The coffee is ${this.strong ? '' : 'not '}strong`)
  },
}

coffee.info() // The coffee is strong

Так как мы называем функцию, которая объявлена внутри Кофе Объект, наш контекст изменяется для именно этого объекта. Теперь мы можем получить доступ ко всем свойствам этого объекта через это Отказ В нашем примере выше, мы также могли просто ссылаться на его напрямую, делая Coffee.strong . Это становится интереснее, когда мы не знаем, какой контекст, какой объект, мы находимся или когда все просто получают немного сложнее. Посмотрите на следующий пример:

const drinks = [
  {
    name: 'Coffee',
    addictive: true,
    info: function() {
      console.log(`${this.name} is ${this.addictive ? '' : 'not '} addictive.`)
    },
  },
  {
    name: 'Celery Juice',
    addictive: false,
    info: function() {
      console.log(`${this.name} is ${this.addictive ? '' : 'not '} addictive.`)
    },
  },
]

function pickRandom(arr) {
  return arr[Math.floor(Math.random() * arr.length)]
}

pickRandom(drinks).info()

Классы и экземпляры

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

Давайте взглянем:

class Coffee {
  constructor(strong) {
    this.strong = !!strong
  }
  info() {
    console.log(`This coffee is ${this.strong ? '' : 'not '}strong`)
  }
}

const strongCoffee = new Coffee(true)
const normalCoffee = new Coffee(false)

strongCoffee.info() // This coffee is strong
normalCoffee.info() // This coffee is not strong

Ловушка: бесшовно вложенная функция звонков

Иногда мы в конечном итоге в контексте мы на самом деле не ожидали. Это может произойти, когда мы неосознанно называем функцию внутри другого контекста объекта. Очень распространенный пример – при использовании сентиментальный или Setinterval :

// BAD EXAMPLE
const coffee = {
  strong: true,
  amount: 120,
  drink: function() {
    setTimeout(function() {
      if (this.amount) this.amount -= 10
    }, 10)
  },
}

coffee.drink()

Как вы думаете, что Coffee.amount является?

..

.

Это все еще 120 Отказ Во-первых, мы были внутри Кофе объект, поскольку пить Метод объявлен внутри этого. Мы только что сделали сентиментальный и ничего больше. Это именно это.

Как я объяснил ранее, Сетримс Метод на самом деле объявлен в окно объект. При звонке, мы на самом деле переключаем контекст к окно опять таки. Это означает, что наши инструкции фактически пытались изменить окно , Но это закончилось ничего не делать из-за Если -утверждение. Позаботиться об этом, мы должны привязывать Наши функции (см. Ниже).

Реагировать

Использование реагирования, это, надеюсь, будет вещь прошлого в ближайшее время, благодаря крючкам. На данный момент мы все еще должны привязывать все (больше на это позже) так или иначе. Когда я начал, я понятия не имел, почему я это делал, но на данный момент вы уже должны знать, почему это необходимо.

Давайте посмотрим на два простых компонента Ract Class:

// BAD EXAMPLE
import React from 'react'

class Child extends React.Component {
  render() {
    return 

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

Я предполагаю, что реагирование вызывает рендеринг метода наших компонентов в другом контексте, через классы помощников или подобных (даже если мне придется копать глубже, чтобы узнать наверняка). Поэтому Это не определен, и мы пытаемся получить доступ this.state.coffeecount. . Вы должны получить что-то вроде Не может прочитать свойство CoffeeCount undefined Отказ

Чтобы решить проблему, вы должны связывать (мы доберемся туда) Методы в наших классах, как только мы передам их из компонента, где они определены.

Давайте посмотрим на еще один общий пример:

// BAD EXAMPLE
class Viking {
  constructor(name) {
    this.name = name
  }

  prepareForBattle(increaseCount) {
    console.log(`I am ${this.name}! Let's go fighting!`)
    increaseCount()
  }
}

class Battle {
  constructor(vikings) {
    this.vikings = vikings
    this.preparedVikingsCount = 0

    this.vikings.forEach(viking => {
      viking.prepareForBattle(this.increaseCount)
    })
  }

  increaseCount() {
    this.preparedVikingsCount++
    console.log(`${this.preparedVikingsCount} vikings are now ready to fight!`)
  }
}

const vikingOne = new Viking('Olaf')
const vikingTwo = new Viking('Odin')

new Battle([vikingOne, vikingTwo])

Мы проезжаем inereasecount от одного класса к другому. Когда мы называем inereasecount Метод Викинг мы уже изменили контекст и это на самом деле указывает на Викинг , что означает, что наше inereasecount Метод не будет работать должным образом.

Решение – связывание

Самое простое решение для нас – привязывать Методы, которые будут переданы из нашего оригинального объекта или класса. Существуют разные способы, где вы можете связать функции, но наиболее распространенным (также в реакции) является связывание его в конструкторе. Поэтому нам придется добавить эту строку в Бой Конструктор до линии 18:

this.increaseCount = this.increaseCount.bind(this)

Вы можете связать любую функцию для любого контекста. Это не значит, что вы всегда должны связать функцию к контексту, он объявляется (это наиболее распространенный случай). Вместо этого вы можете связать это с другим контекстом. С привязывать ты всегда Установите контекст для объявления функции Отказ Это означает, что все призывы к этой функции получит связанный контекст как это Отказ Есть два других помощника для установки контекста.

Применить и вызывать

Они оба делают в основном то же самое, просто синтаксис отличается. Для обоих вы передаете контекст как первый аргумент. Применить принимает массив для других аргументов, с вызов Вы можете просто отделить другие аргументы запятой. Теперь что они делают? Оба эти методы устанавливают контекст для Один специфический вызов функции . При вызове функции без Позвоните Контекст устанавливается на контекст по умолчанию (или даже связанным контекстом). Вот пример:

class Salad {
  constructor(type) {
    this.type = type
  }
}

function showType() {
  console.log(`The context's type is ${this.type}`)
}

const fruitSalad = new Salad('fruit')
const greekSalad = new Salad('greek')

showType.call(fruitSalad) // The context's type is fruit
showType.call(greekSalad) // The context's type is greek

showType() // The context's type is undefined

Можете ли вы угадать, какой контекст последнего showtype () звонок?

..

.

Вы правы, это самый внешний объем, окно Отказ Поэтому Тип это неопределенный нет нет

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

Об авторе: Лукас Гисдер-Дубко соучредин и руководил стартапом в качестве CTO в течение 1 1/2 лет, построение технологической команды и архитектуры. Выйдя из запуска, он преподавал кодировку в качестве инструктора свинца в Ironhack И сейчас строит стартап агентства и консультации в Берлине. Проверить dube.io Узнать больше.

Оригинал: “https://www.freecodecamp.org/news/how-to-understand-the-keyword-this-and-context-in-javascript-cd624c6b74b8/”