Хотя оба они служат одинаковым целям, между этими двумя типами объявлений есть разница. Проверьте следующий пример:

//Function expression
functionOne();
//Error
//"TypeError: functionOne is not a function

var functionOne = function() {
  console.log("functionOne");
};
//Function declaration
functionTwo();
//No error
//Prints - functionTwo

function functionTwo() {
  console.log("functionTwo");
}

Объявление функции

обрабатывается, когда выполнение входит в контекст, в котором оно появляется до выполнения любого пошагового кода. Создаваемой функции присваивается собственное имя (functionTwo() в предыдущем примере), и это имя помещается в область, в которой появляется объявление. Поскольку он обрабатывается перед любым пошаговым кодом в том же контексте, вызов functionTwo() перед его определением работает без ошибок.

Однако functionOne() — это выражение анонимной функции, оцениваемое при достижении его при пошаговом выполнении кода (также называемом выполнением во время выполнения); мы должны объявить его, прежде чем мы сможем его вызвать.

Таким образом, объявление функции functionTwo() было поднято, в то время как функциональное выражение functionOne() выполнялось, когда оно встречалось при построчном выполнении.

ПРИМЕЧАНИЕ:
Поднимаются как объявления функций, так и объявления переменных, но сначала поднимаются функции, а затем переменные.

Следует помнить, что вы никогда не должны использовать объявления функций условно. Это поведение не стандартизировано и может вести себя по-разному на разных платформах. В следующем примере показан такой фрагмент, в котором мы пытаемся условно использовать объявления функций. Мы пытаемся назначить другое тело функции для функции sayMoo(), но такой условный код не гарантирует работу во всех браузерах и может привести к непредсказуемым результатам:

// Never do this - different browsers will behave differently
if (true) {
  function sayMoo() {
    return 'trueMoo';
  }
}
else {
  function sayMoo() {
    return 'falseMoo';
  }
}
foo();

Однако совершенно безопасно и разумно сделать то же самое с функциональными выражениями:

var sayMoo;
if (true) {
  sayMoo = function() {
    return 'trueMoo';
  };
}
else {
  sayMoo = function() {
    return 'falseMoo';
  };
}
foo();

Если вам интересно узнать, почему не следует использовать объявления функций в условных блоках, читайте дальше; в противном случае вы можете пропустить следующий абзац.

Объявления функций могут появляться только в теле программы или функции. Они не могут появляться в блоке ({ ... }). Блоки могут содержать только операторы, а не объявления функций. Из-за этого почти все реализации JavaScript имеют отличное от этого поведение. Всегда рекомендуется никогда не использовать объявления функций в условном блоке.

Функциональные выражения, с другой стороны, очень популярны. Очень распространенный шаблон среди программистов JavaScript — разветвление определений функций на основе некоторого условия. Поскольку такие ответвления обычно происходят в одной и той же области видимости, почти всегда необходимо использовать функциональные выражения.