Объявление неоднозначной функции в Javascript

Я новичок в Javascript и смущен тем, как работает объявление функции. Я сделал несколько тестов и получил некоторые интересные результаты:

say();

function say()
{
    alert("say");
}

Продвинутая декларация работала и всплывала "say"

Напротив

say();

say = function()
{
    alert("say");
}

не работает, хотя он также объявляет объект функции

Если мы объявим функцию и redeclare, то потом:

function say()
{
    alert("speak");
}

say();

function say()
{
    alert("say");
}

Я сказал "сказать" вместо "говорить" . Этот сюрприз!

OK. Кажется, что работает только последнее объявление функции. Затем давайте сначала объявим объект функции, а затем "регулярную" функцию:

say = function()
{
    alert("speak");
}

say();

function say()
{
    alert("say");
}

say();

Еще один сюрприз: "говорить" , а затем "говорить" . Объявление "обычной" функции вообще не срабатывало!

Есть ли объяснение всех из них? И, если "регулярное" объявление функции действительно является "хрупким" и может быть легко переопределено объектом функции с тем же именем, следует ли мне держаться подальше от этого?

Другой вопрос: только с форматом объектного объекта эта декларация становится невозможной? Есть ли способ "имитировать", что в Javascript?

Ответ 1

Javascript работает следующим образом:

Документ анализируется, и объявления function все принимаются во внимание немедленно, прежде чем выполняется выполнение фактических утверждений. Это объясняет ваш первый пример.

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

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

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

Если вы обновите say во время выполнения, то есть замените порядок объявлений в своем последнем примере, вы увидите два разных предупреждения, которые вы ожидаете:

say(); //speak, the global function

function say() {
  alert('speak');
}

var say = function() {
  alert('say');
}

say(); //say, the declared local variable

Ответ 2

say();

function say()
{
    alert("say");
}

Здесь интерпретатор выбирает определение say(), когда он вызывается, и выполняет его.

say();

say = function()
{
    alert("say");
}

Здесь нет определения say() для извлечения - вместо этого вы назначаете анонимную функцию переменной. Интерпретатор не может "найти" это, как будто он может найти декларации вперед.

function say()
{
    alert("speak");
}

say();

function say()
{
    alert("say");
}

Здесь say определяется и затем переопределяется - выигрывает последнее определение.

say = function()
{
    alert("speak");
}

say();

function say()
{
    alert("say");
}

say();

Здесь say - это переменная, указывающая на анонимную функцию (после интерпретации первого оператора). Это имеет приоритет перед любым определением функции, так же, как если бы вы назначили определение функции перед назначением.

Но если у вас

say();

say = function()
{
    alert("speak");
}

say();

function say()
{
    alert("say");
}

Затем вы получите "say", а затем "говорите".

Ответ 3

Вы можете ожидать, что ваши определения функций будут применяться по порядку. Затем все ваши не-методы линии кода будут исполняться по порядку, включая назначение объектов функций. Это объясняет каждый из ваших примеров. Это интересная проблема. Вы действительно не можете назначить объект функции после попытки вызвать его и ожидать, что он будет работать. Однако сначала будет применено определение функции, которое следует за исполняемым кодом.

Ответ 4

Его всегда хорошая идея, вызывающая функцию позже, хотя javascript работает так.

Большинство языков не будут работать таким образом, вместо этого сделайте это.

function say(){
    alert("say");
}

say();

или

say = function(){
    alert("say");
}

say();

или

(function(){
    alert("say");
})();