Обычные значения завершения в основном появляются в пользовательском коде через eval
, хотя даже тогда это не супер распространено. Возвращаемое значение eval
является окончательным значением завершения выполненных операторов. Поскольку eval
выполняет список операторов, например, когда вы запускаете eval("4") === 4
, вы не оцениваете выражение для конкретного значения, включается автоматическая вставка точки с запятой, поэтому вы на самом деле запускаете eval("4;")
и затем получить значение завершения этого оператора.
В будущем семантика значения завершения также, вероятно, повлияет на предложение do
выражения , которое учитывает код, подобный
const value = do {
if (false) {
1;
} else {
2;
}
};
value === 2;
Вы также можете рассматривать ваши примеры как хороший побочный эффект от общей семантики значений завершения в языке. Когда вы throw
или return
из функции, например, сам язык спецификации, по-прежнему пересекает всю функцию. Возврат или бросание, по существу, говорит «значение завершения - это значение» с типом «возврат» или «бросок». Так что, если у вас было
function fn()
if (false) {
return 1;
} else {
2;
}
}
одна ветвь «если» производит внезапное завершение со значением 1
, а другая - нормальное завершение со значением 2
.
Когда выполнение (с точки зрения спецификации) доходит до конца самой функции, оно скажет: «Это возврат / выброс, если так, передайте его вызывающей функции. Если это нормальное завершение» , он просто отбрасывает значение и возвращает undefined
.
Так что на самом деле тот факт, что есть значение завершения, в точности совпадает с возвращаемым значением или выбрасыванием значения исключения, с точки зрения спецификации, в большинстве случаев это просто сбрасывает значение, если оно является не резкое завершение.