Изучая 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}> // => CALLBACK3 - Здесь я вижу, что обработчик события является встроенной функцией, но похоже, что он вызывается из-за () в конце, иногда, как в следующем фрагменте, вы можете видеть, что просто имя функции дано без круглых скобок , разве они не должны быть там также?
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>
);
}Спасибо, но как только вы прочтете это, вы увидите всего 3 примера на похожие темы, так что, надеюсь, не слишком много.
Пожалуйста, задавайте только один вопрос в сообщении.
@Bergi, конечно, они просто казались тесно связанными, поэтому на этот раз я сохранил их в одном посте.
@jobe 3 не имеет прямого отношения к 1 и 2 и заслуживает отдельного вопроса.
@estus справедливое замечание, отмеченное в следующий раз.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


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}?
Какой параметр? Пример в вопросе не содержит параметров. В случае, если должно быть что-то еще, кроме event объекта из события клика, оно должно быть каким-то образом обернуто функцией, onClick = {e => this.showValue('foo')}
@estus Мой первый вопрос с конкретным примером, который я привел, все еще сбивает меня с толку: какова здесь охватывающая область? это класс или это окно? Как я уже сказал, я видел оба ответа, данные в учебниках.
@estus Боюсь, без ссылки на вопросы и цифры, которые я им дал, я не понял остальных ваших объяснений и немного заблудился.
Я обновил ответ, чтобы быть более конкретным. Код содержит комментарии о том, что такое this в данном конкретном случае. Что касается метода класса foo = () =>..., this является экземпляром класса, и ответ объясняет, почему.
@estus Я посмотрю еще раз, было бы проще, если бы порядок соответствовал вопросам.
Я попытался дать информацию в порядке, который имеет смысл. 1 и 2 вопросы не являются независимыми.
@estus Просто сейчас правильно просматриваю ваш ответ - чтобы подтвердить, что я правильно понимаю - нет способа определить такой метод класса? "foo() =>" если так то я понимаю. Синтаксис поля класса в порядке, потому что это уже относится к классу, потому что функция стрелки была фактически определена в конструкторе за кулисами, это правильно? Я думаю, что я понимаю 1 и 2 до сих пор. С 3 я не совсем понимаю, не могли бы вы объяснить немного проще, пожалуйста.
Да, ваше понимание правильное. Что касается 3, я попытаюсь подвести итог. onClick ожидает функцию. this.showValue() === undefined, поэтому onClick = {this.showValue()} просто неправильно, но onClick = {this.showValue} правильно. Это не сработает, потому что showValue не привязан. Попробуйте сделать let onClick = this.showValue; onClick() сами и посмотрите, что получится, он захлебнется this.props, потому что был вызван в неправильном контексте. onClick = {() => this.showValue()} будет работать, потому что он вызывается в правильном контексте.
onClick = {this.showValue} тоже может работать, если showValue является методом стрелки ИЛИ это прото-метод, который был привязан как showValue = this.showValue.bind(this); showValue() {...}.
@estus Я думаю, что понимаю немного яснее, но все же не полностью, почему this.showValue, переданное без скобок, работает как обратный вызов, а со скобками - нет? Конечно, вам нужны круглые скобки для вызова функции, когда происходит щелчок.
Потому что this.showValue — это функция, а this.showValue() — это значение, возвращаемое этой функцией, то есть undefined. Вам не нужно передавать undefined в onClick. Вы можете войти в консоль для проверки. Конечно, вам нужны круглые скобки для вызова функции, когда происходит щелчок. — вызывать не нужно, за вас сделает React. Обратный вызов — это функция, которая позже будет перезвонил. Место, где вы передаете обратный вызов, отвечает за его вызов.
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 Не могли бы вы пролить свет, пожалуйста? на вопрос 1 я видел ответы как для контекста класса, так и для окна.
@джобе developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…. Ответ Эстуса правильный, в стрелочной функции, созданной в конструкторе класса, this относится к экземпляру.
@Bergi А, хорошо, это имеет смысл, но мне интересно, в каком сценарии я видел в некоторых учебниках, где они сказали, что лексическое значение «это» для функции стрелки будет окном, это то, что я нашел запутанным.
@jobe Значение значения this зависит от того, где определена функция стрелки и (если в функции), как эта функция вызывается. Если в учебнике говорилось о стрелочной функции в контексте конструктора class, это было просто неправильно.
@Bergi, я сказал, что это относится к экземпляру, и указал, когда он глобальный, а когда нет, мое намерение состояло в том, чтобы упростить ситуацию.
@Jalal Все еще «относится к текущему объему» неверен (по крайней мере, терминология)
@Bergi, но есть ли способ определить стрелочную функцию в классе вне конструктора? Я тоже ничего не могу придумать. Существует новый синтаксис свойства класса, о котором я только что прочитал, но он также задействуется в конструкторе за кулисами.
@jobe Функция стрелки также может быть определена в обычном методе класса, и тогда ее this зависит от того, как вызывается метод. Обычно на экземпляре, но мало ли.
@Bergi, не могли бы вы привести простой пример, пожалуйста, я не могу его придумать. В моем первом вопросе у меня было это 'clickHandler = () => { }' - но это не будет обычным методом класса, не так ли?
@джоб method() { const arr = () => { console.info(this; }; arr(); }
очень длинный, но хороший вопрос