Visual Studio показывает неправильное значение для `this` в TypeScript

Рассмотрим следующий код:

class Person{
    firstname = ko.observable<string>();
    lastname: ko.observable<string>();
    fullname = ko.computed(()=>{

        // Breakpoint here
        return this.firstname() + ' ' + this.lastname();

    });

когда я отлаживаю Visual Studio 2013, если поставить точку останова и увидеть значение this с помощью часового или немедленного окна, это означает, что значение window не является экземпляром человека. Следовательно, он показывает undefined для this.firstname.

Проверяя преобразованный код JavaScript, я выясню, что я должен проверить значение _this вместо this.

Хотя код работает без ошибок, но он тратит много времени, чтобы понять, что истинное значение переменной this доступно через _this.

Вопрос Я где-то не прав в использовании свойств класса, который вызывает это вводящее в заблуждение значение в значении this? или это просто ошибка? или, может быть, по дизайну почему-то?

Ответ 1

Из-за того, как "это" ключевое слово работает в javascript, скрипт создает псевдоним "_this" для вас. Это по дизайну, и отлично, когда вы знаете, как это работает.

Ваш пример:

  class Person {   firstname = ko.observable <string>();   lastname: ko.observable <string>();   fullname = ko.computed(       () = > {           // Точка останова здесь           return this.firstname() + '' + this.lastname();   });
}
Код>

Скомпилируется:

  var Person = (function() {   function Person() {       var _this = this;       this.firstname = ko.observable();       this.lastname =();       this.fullname = ko.computed(function() {           // Точка останова здесь           return _this.firstname() + '' + _this.lastname();       });   }   возвращение лица;
})();
Код>

Это показывает (как вы упомянули), что "это" в вашей вычисленной функции fullname скомпилировано в "_this". Ваша проблема с отладкой заключается в том, что Visual Studio отлаживает скомпилированный javascript. И в javascript "это" внутри функции означает что-то еще, читайте больше об этом "в javascript здесь.

Typcript создает эту ссылку, когда вы используете функцию лямбда, т.е.

  class foo {
   something: string =  "some string";
   foo1 =() = > {this.something}   foo2() {this.something}
}
Код>

Скомпилируется:

  var foo = (function() {   функция foo() {       var _this = this;       this.something =  "some string";       this.foo1 = function() {_this.something; };   }   foo.prototype.foo2 = function() {this.something; };   return foo;
})();
Код>

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

Короткий ответ для работы с этим - проверить это при работе с лямбдами, пока он не будет исправлен. Для него есть открытая проблема: https:// typescript.codeplex.com/workitem/1655.

Ответ 2

Ну, вы просто наткнулись на одну из проблем JavaScript. "это сводит меня с ума, но я понятия не имею, что это значит". Так что это не ошибка, это по дизайну. Короче говоря, JavaScript rescopes this в соответствии с контекстом. Это особенно проблематично при использовании библиотек, таких как d3 (для обратных вызовов событий) или angular, или нокаутом в вашем случае. Эта проблема становится более очевидной при использовании TypeScript, потому что вы должны использовать this всюду. Вы можете найти дополнительную документацию об использовании this в сети разработчиков mozilla.

Чтобы обойти вашу проблему, самым простым решением является сохранение ссылки на исходный this перед вводом вашего обратного вызова и использование локальной переменной внутри, т.е.:

class Person{
  firstname = ko.observable<string>();
  lastname: ko.observable<string>();
  var self = this;
  fullname = ko.computed(()=>{

    // Breakpoint here
    return self.firstname() + ' ' + self.lastname();

  });

Это привычка, которую я предлагаю вам принять, чтобы избежать будущих проблем, и является хорошей практикой в ​​JavaScript.