Классы, стрелочные функции и ЭТО

Изучая JS и React, я столкнулся с запутанными различиями в учебниках.

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

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

1. Я видел примеры, в которых в учебнике говорится, что значением this будет окно, поскольку функция стрелки наследуется от глобальной/оконной области, но я также видел руководства, в которых говорится, что оно унаследует это от контекста класса - что правильно? если бы вы могли объяснить.

class MyClass {
    value = 'Hello World!'
    clickHandler = () => { console.info(this.value) };
}

2 - у меня есть 2 части этого вопроса - i - Почему синтаксис clickHandler = () => а не clickHandler () =>

Я спрашиваю об этом, потому что я читал, что методы класса могут быть определены с помощью 'functionName () {}', так почему же стрелочные функции обрабатывают имя метода как переменную?

ii - Каково значение этого в приведенном ниже коде? так же, как вопрос 1, я думаю, это относится к объекту окна или классу?

class Foo extends React.Component {
  constructor() {
  }
  clickhandler = () => {
    console.info("you clicked me!!")
  }
  render() {
    return( 
    <div>
      <button onClick = {this.clickhandler}> // => CALLBACK

3 - Здесь я вижу, что обработчик события является встроенной функцией, но похоже, что он вызывается из-за () в конце, иногда, как в следующем фрагменте, вы можете видеть, что просто имя функции дано без круглых скобок , разве они не должны быть там также?

class MyComponent extends React.Component {
  showValue() {
    console.info(this.props.value);
  }

  render() {
    return (
      <button onClick = {() => this.showValue()}>Do Something</button>
    );
  }
}

-------------------------------------------

showValue() {
    console.info(this.props.value);
  }

  render() {
    return (
      <button onClick = {this.showValue}>Do Something</button>
    );
  }

очень длинный, но хороший вопрос

Jalal 23.02.2019 15:58

Спасибо, но как только вы прочтете это, вы увидите всего 3 примера на похожие темы, так что, надеюсь, не слишком много.

j obe 23.02.2019 16:17

Пожалуйста, задавайте только один вопрос в сообщении.

Bergi 23.02.2019 17:33

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

j obe 23.02.2019 23:28

@jobe 3 не имеет прямого отношения к 1 и 2 и заслуживает отдельного вопроса.

Estus Flask 23.02.2019 23:45

@estus справедливое замечание, отмеченное в следующий раз.

j obe 24.02.2019 14:26
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
7
6
3 145
2

Ответы 2

Why is the syntax clickHandler = () => rather than clickHandler () =>

foo () => ... синтаксис недействителен для классов ES6, и эта концепция не имеет смысла. foo() {...} — синтаксический сахар для метода прототипа:

function Class() {}
Class.prototype.foo = function () {
  // this instanceof Class === true
}

Это бы не сработало, если бы Class.prototype.foo была стрелкой; this будет извлекаться из области, где Class определено:

// this === undefined

Class.prototype.foo = () => {
  // this === undefined
}

foo = () => ... — это синтаксис поле класса, который является предложением этапа 3 и не является частью ES6.

class Class {
  foo = () => {
    // this instanceof Class === true 
  }
}

является синтаксическим сахаром для:

class Class {
  constructor() {
    // this instanceof Class === true 
    this.foo = () => {
      // this instanceof Class === true 
    }
  }
}

I've seen examples where a tutorial says the value of this would be window as the arrow function inherits from the global/window scope but I've also seen tutorials where they say it will inherit this from the class context/scope - which is correct?

Функция стрелки становится лексической this из охватывающей области. Если стрелка определена в глобальной области видимости, this — это window, а undefined — в области модуля ES.

В приведенном выше примере стрелка определена в области конструктора класса, this — это экземпляр класса.

Here I see the event handler is an inline function, but it looks like it gets invoked because of the () at the end, sometimes as in the follow on snippet, you can see that just the function name is given without the parentheses, shouldn't they be there also?

Ожидается, что функция обратного вызова будет передана как свойство onClick. this.showValue() вызывает функцию и возвращает из нее значение. Если значение также не является функцией, вызов метода на месте, такого как onClick = {this.showValue()}, неверен.

onClick = {this.showValue} передает метод класса в качестве обратного вызова. Поскольку showValue является методом-прототипом, который не привязан к правильному контексту this, обратный вызов будет выполнен с неправильным контекстом (проблема объяснена в этот вопрос), а onClick = {() => this.showValue()} передает функцию-оболочку как обратный вызов, который выполняет showValue с правильным контекстом.

На самом деле у меня есть аналогичный вопрос по номеру 3, и мне интересно, как нам передать параметр onClick = {this.showValue}?

Isaac 23.02.2019 16:43

Какой параметр? Пример в вопросе не содержит параметров. В случае, если должно быть что-то еще, кроме event объекта из события клика, оно должно быть каким-то образом обернуто функцией, onClick = {e => this.showValue('foo')}

Estus Flask 23.02.2019 17:07

@estus Мой первый вопрос с конкретным примером, который я привел, все еще сбивает меня с толку: какова здесь охватывающая область? это класс или это окно? Как я уже сказал, я видел оба ответа, данные в учебниках.

j obe 23.02.2019 23:30

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

j obe 23.02.2019 23:33

Я обновил ответ, чтобы быть более конкретным. Код содержит комментарии о том, что такое this в данном конкретном случае. Что касается метода класса foo = () =>..., this является экземпляром класса, и ответ объясняет, почему.

Estus Flask 23.02.2019 23:46

@estus Я посмотрю еще раз, было бы проще, если бы порядок соответствовал вопросам.

j obe 24.02.2019 00:10

Я попытался дать информацию в порядке, который имеет смысл. 1 и 2 вопросы не являются независимыми.

Estus Flask 24.02.2019 00:23

@estus Просто сейчас правильно просматриваю ваш ответ - чтобы подтвердить, что я правильно понимаю - нет способа определить такой метод класса? "foo() =>" если так то я понимаю. Синтаксис поля класса в порядке, потому что это уже относится к классу, потому что функция стрелки была фактически определена в конструкторе за кулисами, это правильно? Я думаю, что я понимаю 1 и 2 до сих пор. С 3 я не совсем понимаю, не могли бы вы объяснить немного проще, пожалуйста.

j obe 24.02.2019 21:13

Да, ваше понимание правильное. Что касается 3, я попытаюсь подвести итог. onClick ожидает функцию. this.showValue() === undefined, поэтому onClick = {this.showValue()} просто неправильно, но onClick = {this.showValue} правильно. Это не сработает, потому что showValue не привязан. Попробуйте сделать let onClick = this.showValue; onClick() сами и посмотрите, что получится, он захлебнется this.props, потому что был вызван в неправильном контексте. onClick = {() => this.showValue()} будет работать, потому что он вызывается в правильном контексте.

Estus Flask 24.02.2019 21:20
onClick = {this.showValue} тоже может работать, если showValue является методом стрелки ИЛИ это прото-метод, который был привязан как showValue = this.showValue.bind(this); showValue() {...}.
Estus Flask 24.02.2019 21:21

@estus Я думаю, что понимаю немного яснее, но все же не полностью, почему this.showValue, переданное без скобок, работает как обратный вызов, а со скобками - нет? Конечно, вам нужны круглые скобки для вызова функции, когда происходит щелчок.

j obe 25.02.2019 02:02

Потому что this.showValue — это функция, а this.showValue() — это значение, возвращаемое этой функцией, то есть undefined. Вам не нужно передавать undefined в onClick. Вы можете войти в консоль для проверки. Конечно, вам нужны круглые скобки для вызова функции, когда происходит щелчок. — вызывать не нужно, за вас сделает React. Обратный вызов — это функция, которая позже будет перезвонил. Место, где вы передаете обратный вызов, отвечает за его вызов.

Estus Flask 25.02.2019 02:14

1-this относится к текущей области. В MyClass это относится к экземпляру класса. Так что оба ответа правильные. В глобальной области это относится к окну, внутри myclass это относится к классу.

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

3-onClick = {() => this.showValue()}>Do Something</button>: создает функцию каждый раз, когда щелчок запускает событие. Это полезно, когда в некоторых случаях вы хотите передать дополнительные аргументы от рендеринга компонента в обработчик событий.

onClick = {() => this.showValue(event, id, name)}>Do Something</button>

но с onClick = {this.showValue}>Do Something</button>, что является обычным случаем, вы вызываете обработчик, когда он запускает событие, не создавая каждый раз новую функцию.

Но как он может идентифицировать обработчик? Путем привязки this может распознать, что находится внутри вашей области, потому что вы вызываете это внутри, которое находится showValue

Нет, ключевое слово this никогда не относится к «сфера».

Bergi 23.02.2019 17:34

@Bergi Не могли бы вы пролить свет, пожалуйста? на вопрос 1 я видел ответы как для контекста класса, так и для окна.

j obe 23.02.2019 23:35

@джобе developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…. Ответ Эстуса правильный, в стрелочной функции, созданной в конструкторе класса, this относится к экземпляру.

Bergi 23.02.2019 23:48

@Bergi А, хорошо, это имеет смысл, но мне интересно, в каком сценарии я видел в некоторых учебниках, где они сказали, что лексическое значение «это» для функции стрелки будет окном, это то, что я нашел запутанным.

j obe 23.02.2019 23:52

@jobe Значение значения this зависит от того, где определена функция стрелки и (если в функции), как эта функция вызывается. Если в учебнике говорилось о стрелочной функции в контексте конструктора class, это было просто неправильно.

Bergi 23.02.2019 23:55

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

Jalal 23.02.2019 23:57

@Jalal Все еще «относится к текущему объему» неверен (по крайней мере, терминология)

Bergi 23.02.2019 23:59

@Bergi, но есть ли способ определить стрелочную функцию в классе вне конструктора? Я тоже ничего не могу придумать. Существует новый синтаксис свойства класса, о котором я только что прочитал, но он также задействуется в конструкторе за кулисами.

j obe 24.02.2019 00:09

@jobe Функция стрелки также может быть определена в обычном методе класса, и тогда ее this зависит от того, как вызывается метод. Обычно на экземпляре, но мало ли.

Bergi 24.02.2019 13:27

@Bergi, не могли бы вы привести простой пример, пожалуйста, я не могу его придумать. В моем первом вопросе у меня было это 'clickHandler = () => { }' - но это не будет обычным методом класса, не так ли?

j obe 24.02.2019 14:27

@джоб method() { const arr = () => { console.info(this; }; arr(); }

Bergi 24.02.2019 14:31

Другие вопросы по теме