[javascript] 화살표 함수 (공개 클래스 필드)를 클래스 메서드로 사용하는 방법은 무엇입니까?

나는 React와 함께 ES6 클래스를 처음 사용하고 있는데, 이전에는 메소드를 현재 객체에 바인딩했지만 (첫 번째 예 참조) ES6을 통해 클래스 함수를 화살표가있는 클래스 인스턴스에 영구적으로 바인딩 할 수 있습니까? (콜백 함수로 전달할 때 유용합니다.) CoffeeScript에서 가능한 한 오류를 사용하려고하면 오류가 발생합니다.

class SomeClass extends React.Component {

  // Instead of this
  constructor(){
    this.handleInputChange = this.handleInputChange.bind(this)
  }

  // Can I somehow do this? Am i just getting the syntax wrong?
  handleInputChange (val) => {
    console.log('selectionMade: ', val);
  }

SomeClass.handleInputChange예를 들어 내가 전달한다면 객체가 setTimeout아닌 클래스 인스턴스로 범위가 지정됩니다 window.



답변

구문 이름이 약간 떨어져 속성 이름 뒤에 등호가 없습니다.

class SomeClass extends React.Component {
  handleInputChange = (val) => {
    console.log('selectionMade: ', val);
  }
}

이것은 실험적인 기능입니다. 이것을 컴파일하려면 Babel의 실험 기능을 활성화해야합니다. 다음 은 실험이 가능한 데모입니다.

babel에서 실험 기능을 사용하려면 여기 에서 관련 플러그인을 설치할 수 있습니다 . 이 특정 기능을 사용하려면 transform-class-properties플러그인 이 필요합니다 .

{
  "plugins": [
    "transform-class-properties"
  ]
}

클래스 필드 및 정적 속성 제안에 대한 자세한 내용은 여기를 참조하십시오.



답변

아니요, 바인딩 된 인스턴스 별 메소드를 작성하려면 생성자에서이를 수행해야합니다. 그러나 .bind프로토 타입 방법 을 사용 하는 대신 화살표 기능을 사용할 수 있습니다 .

class SomeClass extends React.Component {
  constructor() {
    super();
    this.handleInputChange = (val) => {
      console.log('selectionMade: ', val, this);
    };
    
  }
}

당신이 생략 할 수 있는 제안 이 있습니다constructor()동일한 기능을 사용하여 과제 과제를 수업 범위에 직접 넣을 있지만 실험적이기 때문에 사용하지 않는 것이 좋습니다.

또는 항상을 사용 .bind하여 프로토 타입에서 메서드를 선언 한 다음 생성자의 인스턴스에 바인딩 할 수 있습니다. 이 접근법은 클래스 외부에서 메소드를 수정할 수 있기 때문에 유연성이 뛰어납니다.

class SomeClass extends React.Component {
  constructor() {
    super();
    this.handleInputChange = this.handleInputChange.bind(this);
    
  }
  handleInputChange(val) {
    console.log('selectionMade: ', val, this);
  }
}


답변

이 질문에 대한 답변이 충분하다는 것을 알고 있지만 실험 기능을 사용하지 않으려는 사람들에게는 약간의 기여를합니다. 생성자에서 여러 함수 바인딩을 바인딩하고 지저분한 것처럼 보이게 만드는 문제 때문에 한 번 생성자에서 바인딩되고 호출 된 유틸리티 메소드가 나타났습니다. 필요한 모든 메소드 바인딩이 자동으로 수행됩니다.

생성자와 함께이 클래스가 있다고 가정합니다.

//src/components/PetEditor.jsx
import React from 'react';
class PetEditor extends React.Component {

   constructor(props){
        super(props);
        this.state = props.currentPet || {tags:[], photoUrls: []};

        this.tagInput = null;
        this.htmlNode = null;

        this.removeTag = this.removeTag.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.modifyState = this.modifyState.bind(this);
        this.handleKeyUp = this.handleKeyUp.bind(this);
        this.addTag = this.addTag.bind(this);
        this.removeTag = this.removeTag.bind(this);
        this.savePet = this.savePet.bind(this);
        this.addPhotoInput = this.addPhotoInput.bind(this);
        this.handleSelect = this.handleSelect.bind(this);

    }
    // ... actual method declarations omitted
}

지저분 해 보이지 않습니까? 이제이 유틸리티 메소드를 만들었습니다.

//src/utils/index.js
/**
 *  NB: to use this method, you need to bind it to the object instance calling it
 */
export function bindMethodsToSelf(objClass, otherMethodsToIgnore=[]){
    const self = this;
    Object.getOwnPropertyNames(objClass.prototype)
        .forEach(method => {
              //skip constructor, render and any overrides of lifecycle methods
              if(method.startsWith('component')
                 || method==='constructor'
                 || method==='render') return;
              //any other methods you don't want bound to self
              if(otherMethodsToIgnore.indexOf(method)>-1) return;
              //bind all other methods to class instance
              self[method] = self[method].bind(self);
         });
}

이제 내가해야 할 일은 해당 유틸리티를 가져 와서 생성자에 대한 호출을 추가하는 것이므로 생성자에서 각각의 새로운 메소드를 더 이상 바인딩 할 필요가 없습니다. 새로운 생성자는 이제 다음과 같이 깨끗해 보입니다.

//src/components/PetEditor.jsx
import React from 'react';
import { bindMethodsToSelf } from '../utils';
class PetEditor extends React.Component {
    constructor(props){
        super(props);
        this.state = props.currentPet || {tags:[], photoUrls: []};
        this.tagInput = null;
        this.htmlNode = null;
        bindMethodsToSelf.bind(this)(PetEditor);
    }
    // ...
}


답변

화살표 함수를 사용하고 있으며 생성자에 바인딩합니다. 따라서 화살표 기능을 사용할 때 바인딩을 할 필요가 없습니다.

class SomeClass extends React.Component {
  handleInputChange = (val) => {
    console.log('selectionMade: ', val);
  }
}

또는 아래와 같이 일반 함수를 사용할 때 생성자에서만 함수를 바인딩해야합니다.

class SomeClass extends React.Component {
   constructor(props){
      super(props);
      this.handleInputChange = this.handleInputChange.bind(this);
   }

  handleInputChange(val){
    console.log('selectionMade: ', val);
  }
}

또한 렌더링에서 직접 함수를 바인딩하는 것은 권장되지 않습니다. 항상 생성자에 있어야합니다


답변