в этом примере в статье о функциях MDN: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Functions
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<script src = "./script/first.js"></script>
<script src = "./script/second.js"></script>
<script>
greeting();
</script>
<title>Document</title>
</head>
<body>
</body>
</html>
// first.js
const name = "Chris";
function greeting() {
alert(`Hello ${name}: welcome to our company.`);
}
// second.js
const name = "Zaptec";
function greeting() {
alert(`Our company is called ${name}.`);
}
почему выполняется первая функция приветствия, но если я изменю имя константы на просто имя
// second.js
name = "Zaptec";
function greeting() {
alert(`Our company is called ${name}.`);
}
выполняется второй метод приветствия?
насколько я понимаю, во втором случае функция приветствия в Second.js поднимается наверх, поэтому она переопределяет первый метод приветствия до того, как будет выдано исключение и скрипт остановлен, но почему этого не происходит в первом случае?
@Keith: На самом деле, я думаю, что здесь все еще есть подъем, потому что в противном случае он должен иметь тот же эффект даже без const
, поскольку переназначение name
все равно не удастся, поскольку name
является const
. Однако при подъеме сначала выполняется второе определение greeting
(успешно), за которым следует неудачное переназначение. В случае, если в обеих строках есть const
, этого не происходит, поскольку тогда ошибка будет SyntaxError
, а не TypeError
, что происходит на этапе синтаксического анализа, а не на этапе выполнения.
@CherryDT То, что происходит, не имеет ничего общего с подъемом, поместите все в один тег сценария, все будет иметь больше смысла. Я думаю, что ОП сбивает с толку то, как загружаются сценарии.
@Keith Я думаю, дело в том, почему первый случай (обе строки с const
) приводит к Hello Chris: welcome to our company
, а второй случай (первая строка с const
, а вторая без) приводит к Our company is called Chris
. И ответ в том, что в первом случае код второго файла вообще не запускается (из-за синтаксической ошибки), а во втором случае он анализируется, а затем начинает выполняться, сначала выполняя определение поднятой функции (даже несмотря на то, что оно физически ниже задания), затем задание, которое теперь завершается с ошибкой времени выполнения.
@CherryDT Обратите внимание, как это говорит ОП в ответ на ваши вопросы -> the two cases both throw an exception so they should both stop the script but one of them doesn't
. IOW: выполнение двух тегов сценария один за другим не работает так же, как один тег сценария со всем кодом. Для одного сценария не имеет значения, какая ошибка выдается, сценарий завершится неудачей и остановится как OP. ожидал.
@Keith Но в этом-то и дело. Почему второе исключение не мешает второму определению greeting
переопределить первое? Из-за подъема. И этого не происходит с первым исключением, поскольку синтаксические ошибки возникают на этапе синтаксического анализа, прежде чем произойдет подъем. (Попробуйте: измените function greeting ()
на greeting = function ()
во втором скрипте, чтобы это было уже не определение функции, а присвоение функционального выражения и, следовательно, больше не поднималось, и оно внезапно снова начало вести себя, как в первом случае.)
@CherryDT Да, я понимаю эту часть. Я также имел в виду, почему ОП ожидал, что в обоих случаях сценарии в целом потерпят неудачу, вы указываете причину, по которой второй анализирует, и я согласен с этим. Моя точка зрения заключалась не в том, что подъема не произошло, а в том, почему поведение в обоих случаях не останавливает все. Надеюсь, это имеет смысл. Я думаю, что оба ответа, возможно, отвечают на разные части вопроса... :)
@CherryDT Я не знал, что синтаксические ошибки обрабатываются таким образом в JS, я думал, что они действуют как любое другое исключение, поэтому останавливают выполнение только тогда, когда они выполняются. Я новичок в JS (начал изучать его неделю назад). Не могли бы вы, ребята, порекомендовать мне хороший бесплатный или платный источник, например книгу, для более глубокого изучения JS?
@mahmoudmirghani Это логично, если подумать, какой может быть альтернатива. Что, если синтаксическая ошибка возникла из-за случайного {
, расположенного перед определением функции?
Я думал, что JS попытается выяснить что-то, как всегда, даже если есть синтаксическая ошибка. но да, это моя вина, что я этого не заметил. в любом случае спасибо.
Потому что первая ошибка — это SyntaxError
, которая возникает перед подъемом, а вторая ошибка — это TypeError
, которая происходит после подъема.
В первом случае получается SyntaxError: Identifier 'name' has already been declared
, вызванный второй строкой const name = ...
.
Если вы удалили оба ключевых слова const
, это «работает», но фактически меняет глобальную переменную window.name
.
Однако, если вы удалите только второе ключевое слово const
, вы получите другую ошибку: TypeError: Assignment to constant variable.
, и действительно, оно использует второе определение greeting
, но с первым name
!
Вы можете задаться вопросом, почему второй случай ведет себя иначе? Это потому, что SyntaxError
происходит во время анализа файла (только чтения, но еще не выполнения). Он терпит неудачу в первой строке и прекращает обработку остальной части файла. С другой стороны, TypeError
происходит во время выполнения, во время выполнения. В этот момент подъем уже состоялся! Второй greeting
уже был перемещен вверх, и новое определение функции уже было выполнено, переопределив предыдущее. Только после этого const name = ...
был выполнен и потерпел неудачу.
Резюме:
Первый случай (const
в обоих файлах): второй файл не удается проанализировать с помощью SyntaxError
. В этом файле ничего не выполняется.
Второй случай (const
только в первом файле): второй файл удалось проанализировать, greeting
поднимается. Начинается выполнение, применяется поднятое greeting
определение, затем const name = ...
не выполняется с TypeError
и дальнейшее выполнение останавливается (но там все равно больше нечего выполнять).
оба случая выдают исключение, поэтому оба должны остановить скрипт, но один из них этого не делает (второй случай)
@mahmoudmirghani Неудачная загрузка скрипта не останавливает загрузку следующих или предыдущих скриптов. Примечание: вы наблюдаете не Javascript, а просто способ загрузки скриптов. Если бы все было в одном скрипте, то переобъявление const
потребовало бы остановил все.
Потому что второй скрипт не загружается из-за переобъявления
const
.. Никакого отношения к поднятию.