Вопросы по машинописной компиляции - PullRequest
2 голосов
/ 21 января 2020

У меня два вопроса по поводу ts.

не скомпилированный код

class K {
  private p = 3;
  public q = 4;
  public r = () => {
    console.log(this.p, this.q);
  };
}

new K().r();

скомпилированный код

var K = /** @class */ (function() {
  function K() {
    var _this = this;
    this.p = 3;
    this.q = 4;
    this.r = function() {
      console.log(_this.p, _this.q);
    };
  }
  return K;
})();
new K().r();

1. Почему закрытые переменные становятся опубликованными c после компиляции?

Я думал, что код будет примерно таким, как показано ниже, чтобы сделать q приватным. Почему ТС не делает этого?

var K = /** @class */ (function() {
  var p = 3;
  function K() {
    var _this = this;
    this.q = 4;
    this.r = function() {
      console.log(p, _this.q);
    };
  }
  return K;
})();
new K().r();

2. Какова роль переноса анонимной функции?

Если она не использует шаблон модуля, анонимная функция кажется бесполезной. Код может быть как ниже, я думаю.

var K = function() {
  var _this = this;
  this.p = 3;
  this.q = 4;
  this.r = function() {
    console.log(_this.p, _this.q);
  };
};
new K().r();

1 Ответ

1 голос
/ 21 января 2020

Почему закрытые переменные становятся опубликованными c после компиляции?

Идея приватных свойств напрямую в экземпляре является очень новой (использование # синтаксис). В действительности Javascript нет такого ключевого слова, как private или public. Объявление свойства private или publi c в Typescript поможет помочь вам и другим, кто читает и использует код , понять, как этот код предназначен для использования, но он не делает его требуется .

По тем же причинам вы можете написать

window.fn = (arg: string) => {
  console.log(arg.slice(5));
};

, а затем, вне проекта, в Javascript написать

window.fn(5);

несмотря на то, что fn принимает только строку.

Если вы хотите сделать свойства фактически недоступными извне, используйте #, например:

class K {
  #p = 3;

Этот синтаксис чрезвычайно новый в Javascript и поддерживается только в Typescript 3.8+. Например,

class K {
  #p = 3;
  public q = 4;
  public r = () => {
    console.log(this.#p, this.q);
  };
}

new K().r();

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

"use strict";
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, privateMap) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to get private field on non-instance");
    }
    return privateMap.get(receiver);
};
var _p;
var K = /** @class */ (function () {
    function K() {
        var _this = this;
        _p.set(this, 3);
        this.q = 4;
        this.r = function () {
            console.log(__classPrivateFieldGet(_this, _p), _this.q);
        };
    }
    return K;
}());
_p = new WeakMap();
new K().r();
Какова роль обертывания анонимной функции?

Все создание класса заключено в IIFE. Иногда кажется, что это ничего не делает, но с некоторыми типами переданного кода это помогает предотвратить ненужную утечку области. Например,

class K {
  #p = 3;
  static foo = 'bar'
  method() {

  }
}

переносится в

"use strict";
var K = /** @class */ (function () {
    function K() {
        _p.set(this, 3);
    }
    K.prototype.method = function () {
    };
    var _p;
    _p = new WeakMap();
    K.foo = 'bar';
    return K;
}());
...