Ошибка TypeScript? `this` разница между синтаксисом` get` и `defineProperty`` get` - PullRequest
2 голосов
/ 26 марта 2020

У меня есть этот код:

var x = {
  x1: 5,
  x2: 7
};

var y = {
  ...x,
  _originalX2: x.x2,
  get x2() {
    console.log(this.x1);
    return 9;
  }
};
console.log(y.x2);

var z = {
  ...x,
  _originalX2: x.x2
};
Object.defineProperty(z, 'x2', {
  get: function() {
    console.log(this.x1);
    return 9;
  }
})
console.log(z.x2);

Когда я запускаю это как JavaScript в браузере или в NodeJS, я получаю вывод:

5
9
5
9

Когда я запускаю тот же код, что и TypeScript (см. https://repl.it/repls/TornHomelyThing), я получаю вывод:

undefined
9
5
9

Я также вижу, что JS TS генерирует из него @ https://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=22&pc=1#code / . G4QwTgBAHhC8EG8oEYBcECsAaaAmdA7AL4DcAUGaJAJ5yJkQQB0LUODEA + gPZgCWAcz4A7EABsAGvihMoudowEBTAC54AFAEoEHRgGNuwgM7cxSpmO4D1KgBZ8js5JvKNGYVQFcwwiAE5XCCIyUjIDY1NzS2tqWVwXCioIAC86HUYWWQUuXkERcSlUGTkQ8gB5ACMAKyU9FSYAEyUAMxElAAUwbgAHJTAVanVknAByORGcBAhlFXRmz2E6vkMtejcIcJMzCysbe0cUBPWPFW9fAI4iIM0wwy2o3eS4hKA

Мой вопрос два раза:

  1. является ли это считать ошибкой в ​​машинописном, учитывая, что тот же самый код в JS имеет различное поведение ?
  2. Есть ли веская причина, по которой this не может ссылаться на x1 в сгенерированном TypeScript JS? Или это ошибка в JS сама по себе?

1 Ответ

3 голосов
/ 26 марта 2020

Это следует считать ошибкой в ​​TypeScript, учитывая, что один и тот же код в JS ведет себя по-разному?

Да, это определенно похоже на ошибку, связанную с передачей Typescript синтаксис распространения объекта. Скомпилированный TS не делает то же самое, что и JS.

. В первом случае вы определяете объект y со свойством x2, которое является геттером:

var y = {
  ...x, 
  _originalX2:x.x2, 
  get x2(){

Таким образом, ссылка на y.x2 позже приводит к вызову геттера. Но в скомпилированном Typescript мы получаем:

var x = { x1: 5, x2: 7 };
var y = Object.assign(
  Object.assign({}, x),
  {
    _originalX2: x.x2,
    get x2() {
      console.log(this.x1);
    }
  }
);

Это приведет к немедленному вызову геттера - геттеры будут вызваны, когда в объекте передан второй или более аргумент внутри Object.assign. И когда вызывается геттер, this ссылается на второй аргумент, этот объект здесь:

{
  _originalX2: x.x2,
  get x2() {
    console.log(this.x1);
  }
}

, который не имеет свойства x1, поэтому он регистрирует undefined.

undefined регистрируется до того, как завершится Object.assign, прежде чем вы перейдете к следующей строке console.log(y.x2);.

. Для более минимального примера:

var y = {
  ...{}, 
  get prop(){
    console.log('should not be invoked immediately');
  }
};

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

var y = Object.assign({}, { get prop() {
        console.log('should not be invoked immediately');
    } });

Если вы сделаете так, чтобы Typescript не не передавал синтаксис распространения объекта, при увеличении цели после ES2017 это сработает. Например, с ESNext вышеупомянутое передается к:

var y = {
    ...{},
    get prop() {
        console.log('should not be invoked immediately');
    }
};
...