2015-12-02 6 views
2

Вид борьбы с этим на данный момент, поскольку я не понимаю, почему это происходит. Я покажу вам контроллер.AngularJS 1.4 с ES6 Классы, это null

class ExampleClassController { 
    constructor($scope, serviceItem, PrepService, consts) { 
     // Services 
     this.serviceItem = serviceItem; 

     // Init Values 
     this.grid = PrepService; 
     this.dates = [ 
      moment().format('x'), 
      moment().add(14, 'days').format('x') 
     ]; 
     // Works fine 
     console.log(this._init()); 

     // Events 
     $scope.$on(consts.events.change, this._init); 
    } 

    _init() { 
     // this.grid = {}; 
     // Returns null 
     console.log(this, "in the init"); 
     return this.serviceItem.get().then((res) => this.grid = res); 
    } 
} 

Вот странная часть, когда я вызываю this._init внутри конструктора, это прекрасно. Возвращает обещание, как было предложено. Но когда я называю это в $ scope. $ On event, он просто разваливается и говорит, что это значение равно null. Я не могу понять, почему это происходит, поскольку, похоже, это не похоже на чей-либо пример. Все было бы полезно, просто понять, почему было бы здорово.

Спасибо!

+1

Вы теряете ссылку на 'this' при использовании обратного вызова. Вы можете сделать 'this._init.bind (this)' в '$ scope. $ On' – Pierrickouw

+0

Как вы знаете, использовать функцию стрелки в' _init'? '.then ((res) => this.grid = res);' - применить ту же логику к вашему 'constructor' – CodingIntrigue

ответ

3

Как отметил @Pierrickouw в комментариях к вашему вопросу, вы теряете ссылку на this. У вас есть несколько вариантов, чтобы преодолеть это, хотя:

  • Используйте Function.prototype.bind метод

    // Events 
    $scope.$on(consts.events.change, this._init.bind(this)); 
    
  • Используйте стрелки функций (которые имеют свойство удерживать правый контекст)

    // Events 
    $scope.$on(consts.events.change,() => this._init()); 
    
  • Использование функции углового связывания (это только вариант первого варианта)

    // Events 
    $scope.$on(consts.events.change, angular.bind(this, this._init)); 
    

В качестве лучшей практики, вы должны использовать либо привязку или функцию стрелки в зависимости от вашего использования случае.

  1. Если вы хотите просто передать свой обработчик с правом контекста использование .bind

    // .bind(theRightContext), e.g. this or $scope 
    $scope.on('someEvent', this._init.bind(this)); 
    
  2. Если вы хотите сделать некоторые предварительные расчеты вы должны использовать arrow function.

    $scope.on('someEvent',() => { 
         // do some computations here 
         console.log('will now call someMethod on', this); 
         this.someMethod(); 
    }); 
    

Обратите внимание, что arrow function от ES6 эквивалентно использованию .bind в ES5:

$scope.on('someEvent', function() { 
     // do some computations here 
     console.log('will now call someMethod on', this); 
     this.someMethod(); 
}.bind(this)); 
+0

Что вы считаете лучшей практикой? Мне нравится метод .bind (this), но это только потому, что он более визуально привлекателен. Я чувствую, что .bind - это путь, но просто не уверен. –

Смежные вопросы