поведение этого ключевого слова в классах и реагирующий компонент (функция стрелки против обычной функции) - PullRequest
0 голосов
/ 16 марта 2020

Я пытаюсь понять поведение этого ключевого слова в реагирующем компоненте (функция Arrow против обычной функции) в паре с обработчиком событий.

Для этого я создал два примера, один с HTML / vanilla JS, другой с React.

HTML / Vanilla JS

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button class="btn-arr">Log this Arr</button>
    <button class="btn-reg">Log this Reg</button>

    <script>

        class App {
            logThisArr = () => {
                console.log('Arr : ', this);
            };
            logThisReg = function () {
                console.log('Reg : ', this);
            };
        }

        const app = new App();

        const btnArr = document.querySelector('.btn-arr');
        const btnReg = document.querySelector('.btn-reg');

        btnArr.addEventListener('click', app.logThisArr); // Arr : App {logThisArr: ƒ, logThisReg: ƒ}

        btnReg.addEventListener('click', app.logThisReg); // Reg : <button class="btn-reg">Log this Reg</button>

    </script>
</body>

</html>

React

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';

class App extends Component {
    logThisArr = () => {
        console.log('arrow : ', this);
    };
    logThisReg = function() {
        console.log('Reg : ', this);
    };

    render() {
        return (
            <div className="App">
                <button onClick={this.logThisArr}>Log this Arr</button>
                {/* Arr : App {props: {…}, context: {…}, refs: {…}, updater: {…}, logThisArr: ƒ, …}*/}

                <button onClick={this.logThisReg}>Log this Reg</button>
                {/*Reg : undefined */}
            </div>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

Почему я не получаю такой же вывод при использовании обычной функции? В ответ я получаю "undefined", а в ванили JS я получаю объект кнопки.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 17 марта 2020

Хорошо, спасибо вам обоим.

Думаю, я немного лучше понял после большого прочтения.

Это намного глубже, чем в оригинальном посте. Сначала нам нужно понять разницу между «контекстом выполнения» и «лексической областью действия». http://ryanmorr.com/understanding-scope-and-context-in-javascript/

Тогда мы можем начать смотреть на поведение «this» в обычных и стрелочных функциях.

Внутри обычных функций:

  • Значение «this» изменяется в зависимости от «контекста выполнения», другими словами, «this» является ссылкой на того, кто или что вызвал его (обычно это объект, IE объект кнопки или объект, созданный в классе).
  • Если «ничто» не вызвало его (особенно в случае с обратными вызовами), то «this» теряет свою ссылку на исходный объект, который вызвал его, и устанавливается в значение по умолчанию (это значение по умолчанию зависит от того, мы находимся в узле, или в браузере, или в строгом режиме, или используем библиотеку (не уверен насчет библиотеки, но я думаю?))
  • Значение "this" можно явно указать с помощью "call ()" , "apply ()" и "bind ()".

Внутренние функции стрелок:

  • Функция стрелки не имеет своего собственного "контекста выполнения"
  • Функция стрелки статически связывает контекст с объявленным Иными словами, значение «this» является «захваченным» ПОСТОЯННО, и ПОЧТИ ВСЕГДА ссылается на значение «this» «родительской / включающей лексической области видимости» функции (= родительский контекст).
  • Значение «this» никогда не может быть повторно привязано. Но другие параметры внутри функции стрелки могут быть связаны с ключевым словом "bind ()".
  • В особом случае определения методов с помощью функций стрелки в литерале объектов "this" относится к объекту окна. : https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/

Вот почему в реакции необходимо использовать функции со стрелками или ".bind ()", потому что мы не можем полагаться на обычные функции (в который "this" постоянно меняется) для доступа к атрибутам нашего экземпляра объекта класса App.

В нашем конкретном случае c, почему я получаю "undefined" при использовании обычной функции в Код реагирования, TBT Я не совсем уверен (возможно, из-за реакции внутренних махинаций), но я могу догадаться, что это из-за двух вещей:

  • "this" утратило свой "контекст исполнения" (другими словами он потерял свою ссылку на вызывающий его объект), поэтому он становится значением по умолчанию (либо «undefined», когда в «строгом режиме», либо «оконным объектом», когда он не в строгом режиме и в браузере) * 1 042 *
  • В классах ES6 неявная настройка по умолчанию установлена ​​на "строгий режим", поэтому мы получаем "неопределенный".

В любом случае, это не является исчерпывающим, и я еще не все понял , но теперь я немного лучше понимаю, почему нам нужно связывать / использовать функции стрелок в React и как они работают.

Это действительно помогло мне разобраться в сути дела:

А также ссылка, упомянутая @brian Thomoson: Как получить доступ к правильному `this` внутри обратного вызова?

Спасибо, ребята.

С уважением,

0 голосов
/ 16 марта 2020

Вам не нужно обрабатывать this. Но не забудьте привязать события обратного вызова ( React Do c о событиях ), чтобы всегда иметь хороший ref

Просто добавьте это в Приложение Компонент

  constructor(props) {
    super(props);
    this.logThisArr = this.logThisArr.bind(this);
    this.logThisReg = this.logThisReg.bind(this);
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...