Почему ключевые слова `async` и` await` могут быть назначены? - PullRequest
4 голосов
/ 03 июля 2019

Я заметил, что ключевому слову async можно присвоить любое значение и даже использовать как обычную переменную:

let async = "world";

console.log(async)
console.log("Hello " + async)

Тем не менее, даже тогда он продолжает работать как прежде:

let async = "world";

async function foo(input) {
  return input;
}

let barPromise = foo("bar");

console.log("bar promise is:", typeof barPromise);

console.log("bar promise also has a .then:", typeof barPromise.then === "function");

barPromise
  .then(output => console.log("bar promise returns:", output));

console.log("async is still assigned:", async);

foo("Hello ")
  .then(output => console.log(output + async));

Даже await делает то же самое:

let await = "world";

console.log("await is:", await)

async function foo(input) {
  return input;
}

async function bar(input) {
  console.log("before");
  
  let output = await foo(input);
  console.log(output);
  
  console.log("after");
}

bar("hello")

Что здесь происходит? Почему ключевые слова можно использовать в качестве переменных?

1 Ответ

8 голосов
/ 03 июля 2019

Ответ изначально сбивает с толку, но впоследствии имеет смысл

  • , ключевое слово async отсутствует.Существует async function конструкция (MDN) : ссылка на спецификации .Таким образом, async имеет особое значение, только если за ним следует функция - либо как выражение (как традиционная функция, так и функция со стрелкой) или как объявлениеТаким образом, переменная , называемая async, является действительной, поскольку переменная, за которой следует function, не является синтаксически допустимой.Нет столкновения с семантикой:

let foo;

//function declaration
foo function bar() {}; //SyntaxError

let foo;

//function expression
let bar = foo function() {}; //SyntaxError
  • как для await, это на самом деле оператор, а не ключевое слово, и он является частью выражения await (MDN) : ссылка на спецификацию .Семантика требует, чтобы за await следовало унарное выражение и , чтобы быть внутри функции async - что-то, что все еще не синтаксически допустимо с другими переменными.

У меня нет источника для этого, но разумно сделать вывод, что это было сделано для сохранения обратной совместимости.Если бы в ES5 был код, который использовал async в качестве переменной, он внезапно сломался бы позже.Делая async допустимым только в том случае, если в противном случае вы получите SyntaxError, которая обеспечивает сосуществование старого кода и нового кода.То же самое для await.

Интересно, что семантика await на самом деле приводит к поведению, которое снова изначально странно - вы не можете использовать его как переменную внутри функции async.Либо объявив это:

async function foo() {
 let await = "world"; //SyntaxError - not a valid identifier here
}

Нет доступа к нему:

let await = "world"; //valid identifier

async function foo() {
  console.log(await); //SyntaxError - it is not followed by an expression
}

Это также изначально сбивает с толку, однако имеет смысл для обратной совместимости.Даже если бы в предыдущем коде ES6 в качестве переменной использовался await, он не использовал бы его в async функциях, поскольку их не было.Итак, старый код работает и до сих пор нет столкновений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...