'this'는 JavaScript 클래스 메서드에서 정의되지 않았습니다.


86

저는 JavaScript를 처음 사용합니다. 내가 실제로 한 모든 것은 기존 코드를 수정하고 약간의 jQuery를 작성한 것입니다.

이제 속성과 메서드가있는 "클래스"를 작성하려고하지만 메서드에 문제가 있습니다. 내 코드 :

function Request(destination, stay_open) {
    this.state = "ready";
    this.xhr = null;
    this.destination = destination;
    this.stay_open = stay_open;

    this.open = function(data) {
        this.xhr = $.ajax({
            url: destination,
            success: this.handle_response,
            error: this.handle_failure,
            timeout: 100000000,
            data: data,
            dataType: 'json',
        });
    };

    /* snip... */

}

Request.prototype.start = function() {
    if( this.stay_open == true ) {
        this.open({msg: 'listen'});
    } else {

    }
};
//all console.log's omitted

문제는에,이다 Request.prototype.start, this정의되어 있지 않습니다 따라서 문 평가되면 false로. 내가 여기서 뭘 잘못하고 있니?


에 이유 startprototype있습니까?
xj9

무엇으로 Request.prototype설정되어 있습니까?
Matt Ball

여기에 비슷한 질문이 있습니다. stackoverflow.com/questions/3198264/… 여기 에는 유용한 링크가 많이 있습니다. 핵심은 this자바 와 같은 대부분의 OO 언어 에서처럼 자바 스크립트 에서 호출되는 프로토 타입 함수의 '소유자'에 대한 지속적인 참조 가 아니라는 것입니다.
Marc Bollinger

1
@Matt : 요청은 생성자 함수입니다. Request.prototype의 기본값은 new Object(). 여기에 추가하는 모든 항목은을 사용하여 만든 개체의 속성이됩니다 new Request().
Chetan S

@Matt Ball Request.prototype은 인스턴스가 Request상속되는 곳입니다. 이 경우 아마도 Function또는 Object입니다.
xj9

답변:


68

시작 기능을 어떻게 호출하고 있습니까?

이것은 작동합니다 ( 새로운 것이 핵심입니다)

var o = new Request(destination, stay_open);
o.start();

직접처럼 호출 할 경우 Request.prototype.start(), this(글로벌 컨텍스트를 참조합니다 window브라우저에서).

또한 this정의되지 않은 경우 오류가 발생합니다. if 표현식은 false로 평가되지 않습니다.

업데이트 : this객체가 선언에 따라 설정되지 않고 호출에 의해 설정 됩니다 . 의미하는 바는 함수 속성을 같은 변수에 할당 x = o.start하고 호출 x()하면 this내부 시작이 더 이상 참조하지 않는다는 것 o입니다. 이것은 당신이 할 때 일어나는 일 setTimeout입니다. 작동하려면 대신 다음을 수행하십시오.

 var o = new Request(...);
 setTimeout(function() { o.start(); }, 1000);

나는 setTimeout을 사용하고 있습니다 :var listen = new Request(destination, stay_open); setTimeout(listen.start, 500);
Carson Myers

이것은 내가 표현하기 위해 전달한 함수의 basicAuth 가 동일한 출력으로 작동하지 않는 이유를 이해하려고 노력했을 때 내 생명을 구했습니다 .
Edison Spencer

또는 o.start.bind(o). 왜 작동하지 x = o.start; x()않습니까?
theonlygusti

.bind()제자리에서 작동하지 않는 새 함수를 반환합니다. 당신은해야 할 것입니다 그래서 x = o.start.bind(o); x()o.start = o.start.bind(o); x=o.start; x()
ceedob

39

함수가 고차 함수 (인수로 전달됨)로 사용 된 후 범위 this가 손실 되었기 때문에 때때로이 오류가 발생한다는 점을 지적하고 싶었 습니다. 이러한 경우 이러한 함수를 this. 예

this.myFunction.bind(this);

3
좋은 설명 !! 그것이 바로 제가 찾던 것입니다.
vandersondf

1
그냥 나를 구원 얼마나 많은 두통 아무런 이야기가 없다
기본 코더

범위를 this잃는 이유는 무엇 입니까?
theonlygusti

17

자바 스크립트의 OOP는 약간 펑키하고 (또는 많이) 익숙해지는 데 약간의 시간이 걸립니다. 가장 먼저 명심해야 할 것은 수업이 없으며 수업 측면에서 생각하면 당신을 괴롭힐 수 있다는 것입니다. 생성자 (클래스 정의에 해당하는 JavaScript)에 연결된 메서드를 사용하려면 개체를 인스턴스화해야합니다. 예를 들면 :

Ninja = function (name) {
    this.name = name;
};
aNinja = new Ninja('foxy');
aNinja.name; //-> 'foxy'

enemyNinja = new Ninja('boggis');
enemyNinja.name; //=> 'boggis'

참고 Ninja인스턴스가 같은 특성을 가지고 있지만 aNinja의 속성에 액세스 할 수 없습니다 enemyNinja. (이 부분은 정말 쉽고 간단해야합니다.)에 항목을 추가하기 시작하면 상황이 약간 달라집니다 prototype.

Ninja.prototype.jump = function () {
   return this.name + ' jumped!';
};
Ninja.prototype.jump(); //-> Error.
aNinja.jump(); //-> 'foxy jumped!'
enemyNinja.jump(); //-> 'boggis jumped!'

this생성자가 인스턴스화 될 때 (그렇지 않으면 window브라우저에서 전역 개체를 가리킴) 올바른 객체 ( "클래스") 만 가리 키기 때문에 이것을 직접 호출하면 오류가 발생 합니다.


6

ES2015에서 일명 ES6 classfunctions.

컨텍스트를 강제로 설정 this하려면 bind()메소드 를 사용할 수 있습니다 . @chetan이 지적했듯이 호출시 컨텍스트도 설정할 수 있습니다! 아래 예를 확인하십시오.

class Form extends React.Component {
constructor() {
    super();
  }
  handleChange(e) {
    switch (e.target.id) {
      case 'owner':
        this.setState({owner: e.target.value});
        break;
      default:
    }
  }
  render() {
    return (
      <form onSubmit={this.handleNewCodeBlock}>
        <p>Owner:</p> <input onChange={this.handleChange.bind(this)} />
      </form>
    );
  }
}

여기서 우리는 내부 컨텍스트 handleChange()Form.


6
생성자에서 이것에 함수를 바인딩해야합니다. 그렇지 않으면 render클래스가 인스턴스화 될 때 한 번이 아니라 호출 될 때 마다 바인딩합니다 . 또한 대부분의 예는 질문과 실제로 관련이 없습니다.
erich2k8

또는 정의 할 때 화살표 구문을 사용하십시오.handleChange()
Nitin

0

이 질문에 대한 답변이 있었지만 다른 사람이 여기에 올 수도 있습니다.

또한 this클래스를 초기화 할 때 어리석게도 클래스의 메서드를 구조화하려고 할 때 정의되지 않은 문제가있었습니다 .

import MyClass from "./myClass"

// 'this' is not defined here:
const { aMethod } = new MyClass()
aMethod() // error: 'this' is not defined

// So instead, init as you would normally:
const myClass = new MyClass()
myClass.aMethod() // OK


0

화살표 기능 사용 :

Request.prototype.start = () => {
    if( this.stay_open == true ) {
        this.open({msg: 'listen'});
    } else {

    }
};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.