this не определено в методах класса JavaScript - PullRequest
58 голосов
/ 25 октября 2010

Я новичок в 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 не определено и, следовательно, оператор if оценивается как ложный. Что я здесь не так делаю?

Ответы [ 3 ]

55 голосов
/ 25 октября 2010

Как вы вызываете функцию запуска?

Это должно работать ( новый ключ)

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

Если вы прямо называете его как Request.prototype.start(), this будет ссылаться на глобальный контекст (window в браузерах).

Кроме того, если this не определено, это приводит к ошибке. Выражение if не оценивается как ложное.

Обновление : this объект не устанавливается на основе объявления, но вызывает . Это означает, что если вы присваиваете свойство функции такой переменной, как x = o.start, и вызываете x(), this внутри start больше не ссылается на o. Это то, что происходит, когда вы делаете setTimeout. Чтобы заставить это работать, сделайте это вместо:

 var o = new Request(...);
 setTimeout(function() { o.start(); }, 1000);
15 голосов
/ 25 октября 2010

ООП JavaScript немного прикольный (или много) и требует некоторого привыкания.Первое, что вам нужно иметь в виду, это то, что нет классов , и мысль о классах может сбить вас с толку.И чтобы использовать метод, присоединенный к Конструктору (эквивалент 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!'

все будет немного по-другому.правильный объект (ваш "класс") при создании экземпляра конструктора (в противном случае он указывает на глобальный объект, window в браузере)

4 голосов
/ 12 марта 2016

В ES2015 или ES6, class является синтаксическим сахаром для functions.

Если вы хотите принудительно установить контекст для 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.

...