Различные результаты между назначением объекта и распространением объекта - PullRequest
0 голосов
/ 27 апреля 2020

Я использую машинопись и компилирую в ES2016. Я заметил, что я вызываю две разные функции с похожим this объектом в Function.prototype.call(). Я попытался объединить оба this объекта, используя общий объект, который использовал бы ...spread в начале объекта, вот так:

let selfShared = {
  props,
  // ...
};

let selfHost = {
  ...selfShared,
  // ...
};

let selfGuest = {
  ...selfShared,
  // ...
};

Идея использования спреда в начале была в том, что я мог перезаписать общие свойства в любом из this объектов, если я посчитал нужным. Но в отличие от установки props прямо в this объектах с использованием спреда, мы получили странные результаты, которые оказались, потому что tsc скомпилировал код как

let selfShared = {
  props
};

let selfHost = Object.assign(Object.assign({}, selfShared), {
  // ...
});

// ...

, используя мой код

let state = undefined;
let attributes = {};
let selfShared = {
  props: attributes
};

let selfHost = {
  ...selfHost,
  get state() {
    console.log("selfHost get state");
    return state;
  },
  set state(originalStates) {
    console.log("selfHost set state");
    !state ? state = originalStates : console.error("`this.states` already defined in the host function.");
  }
}

вывод выглядит как

let state = undefined;
let attributes = {};
let selfShared = {
  props: attributes
};

let selfHost = Object.assign(
  Object.assign({}, selfShared), {
  get state() {
    console.log("selfHost get state");
    return state;
  },
  set state(originalStates) {
    console.log("selfHost set state");
    !state ? state = originalStates : console.error("`this.states` already defined in the host function.");
  }
});

, теперь, по крайней мере, на firefox 74–77, вставляя оба кода в консоль и добавляя

// ...
selfHost.state = {
  thing: "some"
};
selfHost.state = {
  some: "thing"
};

, выбрасывает разные журналы ... Предварительно скомпилированный код дает мне два set state и ошибку, которые являются ожидаемыми выходными данными, но скомпилированный код дает мне get state и игнорирует правило при set state выводе

{
  some: "thing"
}

вместо ожидаемого

{
  thing: "some"
}

, как в предварительно скомпилированном коде?

Если установить распространение внизу файла, компилируется в

let selfHost = Object.assign({
  get state() {
    console.log("selfHost get state");
    return state;
  },
  set state(originalStates) {
    console.log("selfHost set state");
    !state ? state = originalStates : console.error("`this.states` already defined in the host function.");
  }
}, selfShared);

, что дает правильный вывод, но не позволяет мне перезаписать свойства, заданные selfShared.

Можете ли вы объяснить, почему это происходит с Object.assign и если есть хитрость, чтобы получить вывод из tsc, который все еще позволяет мне делать то, что я изначально хотел?

1 Ответ

0 голосов
/ 29 апреля 2020

При использовании спреда

let obj = {
  ...otherObj,
  // ...
}

или

let obj = Object.assign({}, otherObj, {
  // ...
})

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

Сеттеры и геттеры работают так, как написано в вопросе, когда спред записывается в конце как

let obj = {
  // ...
  ...otherObj
}

или

let obj = Object.assign({
  // ...
}, otherObj)

, поскольку otherObj расширяет только уникальные объекты.

...