Javascript ООП this странно държание

+4 гласа
104 прегледа
попитан 2016 юни 22 в PHP от VeskoNikolov (1,640 точки)

Преди да започна със самият въпрос ще дам една TODO задачка за модераторите:
При създаване на секция за JS, нека този въпрос бъде преместен там. Благодаря.

Сега към самият въпрос.

Пиша едно приложение, което ползва JS и се опитвам да го напиша възможно най-четливо и правилно, което ме доведе до ползването на ООП, колкото и ограничено да е то в JS.

Имам следният код:

var some_object = {
  ajax_url:'http://localhost/',
  some_property:'sdfasdfasdfasgsdf',

  connectMethod: function(){
    $.ajax({
      method: "GET",
      url: this.ajax_url,
      success: function(data){
        this.dataProcessorMethod(data); //ето тук излиза грешката. Защо?
      }
    });
  },

  dataProcessorMethod: function(data){
    console.log(data);
  }
}

Той хвърля следната грешка в конзолата: 

Uncaught TypeError: this.dataProcessorMethod is not a function

Защо се случва това?

1 отговор

0 гласа
отговорени 2016 юни 22 от VeskoNikolov (1,640 точки)
избран 2016 юли 5 от Mitko Vasilev
 
Най-добър отговор

Грешката идва от факта, че this вече не е същия обект там, където се ползва за извикване на dataProcessorMethod. Нека демонстрирам с код:

var some_object = {
  ajax_url:'http://localhost/',
  some_property:'sdfasdfasdfasgsdf',

  connectMethod: function(){
    $.ajax({ //ето тук се създава нов, анонимен обект (оцветен в червено).
      method: "GET",
      url: this.ajax_url,
      success: function(data){ //от този момент нататък this се обръща към създаденият анонимен обект.
        this.dataProcessorMethod(data); //тук излиза грешката защото обектът this няма метод dataProcessorMethod
      }
    });
  },

  dataProcessorMethod: function(data){
    console.log(data);
  }
}

Така оцветено е по-лесно да се види причината за грешката. А именно факта, че this вече се обръща към обекта в червено, а не към some_object.

Решението се състои в следните промени:

var some_object = {
  ajax_url:'http://localhost/',
  some_property:'sdfasdfasdfasgsdf',

  connectMethod: function(){
    $.ajax({
      method: "GET",
      url: this.ajax_url,
      parent: this, //добавяме този ред. тук this се обръща към some_object
      success: function(data){
        this.parent.dataProcessorMethod(data); // и след това се обръщаме към this.parent, което е some_object
      }
    });
  },

  dataProcessorMethod: function(data){
    console.log(data);
  }
}

Това решение е един вид "hack", но върши работа.

...