Sintaxe da classe Javascript e vinculando-a a métodos [duplicado]

Dec 09 2020

Eu queria entender a diferença básica entre como funciona a sintaxe abaixo.

// Syntax 1
class Component extends React.Component {
  constructor(props) {
    super(props)
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick() {
    // ...
  }
}

// Syntax 2

handleClick = () => {
  console.log('this is:', this)
}
<button onClick={this.handleClick}>
  {'Click me'}
</button>

Enquanto a sintaxe 1 precisa de uma ligação explícita a ser especificada dentro do construtor. No entanto, parece que com a sintaxe 2, isso não é necessário. Como a sintaxe 2 consegue realizar a vinculação automaticamente?

Presumo que este entendimento / sintaxe pode ser estendido para qualquer estrutura, incluindo React, Angular, Ember, etc

Respostas

1 CertainPerformance Dec 09 2020 at 11:52

Os campos de classe - ou seja, propriedades definidas diretamente dentro do corpo da classe - são essencialmente apenas açúcar de sintaxe para a mesma coisa dentro do construtor. Então, é isso:

class Something {
  handleClick = () => {
    console.log('this is:', this)
  }
}

é, desugared:

class Something {
  constructor() {
    this.handleClick = () => {
      console.log('this is:', this)
    };
  }
}

Com a adição de açúcar removida, deve ficar claro o que está acontecendo - a função de seta significa que thisse refere ao que thisestá no construtor, que é a própria instância, sem a necessidade de vinculação.

Isso não é apenas uma coisa do React ou do framework - essas são regras padrão no JavaScript vanilla.

Se você não vincular o método ou usar uma função de seta ou algo parecido, então:

<button onClick={this.handleClick}>

falha pela mesma razão que

someButton.addEventListener('click', myObj.someFn)

também falhará ao chamar someFncom um contexto de chamada de myObj- tudo que o navegador sabe é chamar o retorno de chamada passado para o ouvinte de clique; o contexto de chamada de myObjse perde quando passado assim.