Var functionName = function () {} vs functionName () {}

Недавно я начал поддерживать чужой код JavaScript. Я исправляю ошибки, добавляю функции, а также пытаюсь привести код в порядок и сделать его более согласованным.

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

Двумя способами являются:

var functionOne = function() {
    // Some code
};
function functionTwo() {
    // Some code
}

Каковы причины использования этих двух разных методов и каковы плюсы и минусы каждого из них? Есть ли что-нибудь, что можно сделать одним методом, чего нельзя сделать другим?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
7 125
0
1 075 210
37
Перейти к ответу Данный вопрос помечен как решенный

Ответы 37

Ответ принят как подходящий

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

Например, выражение функции:

// TypeError: functionOne is not a function
functionOne();

var functionOne = function() {
  console.info("Hello!");
};

И объявление функции:

// Outputs: "Hello!"
functionTwo();

function functionTwo() {
  console.info("Hello!");
}

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

'use strict';    
{ // note this block!
  function functionThree() {
    console.info("Hello!");
  }
}
functionThree(); // ReferenceError

Определения функций выполняются, когда код входит в окружающий блок, а не когда он входит в включающую функцию. Я не знаю, всегда ли так работало, но было бы неизбежно, если бы блок использовал let или const для определения переменной, которая была закрыта функцией внутри него, и последовательное применение этого правила, вероятно, лучше, чем применение только его. когда неизбежно.

supercat 27.10.2020 00:37

Предложение «из-за подъема» может создать неверное впечатление, что поднимается только названная функция. Фактически, как var functionOne, так и function functionTwo в какой-то степени поднимаются - просто functionOne имеет значение undefined (вы могли бы назвать это полуподъемом, переменные всегда поднимаются только до этой степени), тогда как function functionTwo полностью поднят, поскольку он определены и объявлены. Вызов чего-то неопределенного, конечно же, вызовет ошибку typeError.

rails_has_elegance 04.12.2020 22:19

Спасибо Грегу и @Ben_Aston за объяснение разницы. Но не мог бы кто-нибудь из вас также пролить свет на «за» и «против», когда спрашивает пользователь?

R. Hoek 27.01.2021 11:05

Сначала я хочу исправить Грега: function abc(){} тоже ограничен - имя abc определено в области, где встречается это определение. Пример:

function xyz(){
  function abc(){};
  // abc is defined here...
}
// ...but not here

Во-вторых, можно комбинировать оба стиля:

var xyz = function abc(){};

xyz будет определяться как обычно, abc не определен во всех браузерах, кроме Internet Explorer - не полагайтесь на его определение. Но это будет определено внутри его тела:

var xyz = function abc(){
  // xyz is visible here
  // abc is visible here
}
// xyz is visible here
// abc is undefined here

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

function abc(){};
var xyz = abc;

В этом случае и xyz, и abc являются псевдонимами одного и того же объекта:

console.info(xyz === abc); // prints "true"

Одной из веских причин для использования комбинированного стиля является атрибут «имя» функциональных объектов (не поддерживается Internet Explorer). В основном, когда вы определяете такую ​​функцию, как

function abc(){};
console.info(abc.name); // prints "abc"

его имя присваивается автоматически. Но когда вы определяете это как

var abc = function(){};
console.info(abc.name); // prints ""

его имя пустое - мы создали анонимную функцию и присвоили ее некоторой переменной.

Еще одна веская причина использовать комбинированный стиль - использовать короткое внутреннее имя для обозначения самого себя, предоставляя при этом длинное неконфликтное имя для внешних пользователей:

// Assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
  // Let it call itself recursively:
  shortcut(n - 1);
  // ...
  // Let it pass itself as a callback:
  someFunction(shortcut);
  // ...
}

В приведенном выше примере мы можем сделать то же самое с внешним именем, но оно будет слишком громоздким (и медленнее).

(Другой способ обозначить себя - использовать arguments.callee, который все еще относительно длинный и не поддерживается в строгом режиме.)

В глубине души JavaScript трактует оба утверждения по-разному. Это объявление функции:

function abc(){}

abc здесь определяется повсюду в текущей области:

// We can call it here
abc(); // Works

// Yet, it is defined down there.
function abc(){}

// We can call it again
abc(); // Works

Кроме того, он поднялся с помощью заявления return:

// We can call it here
abc(); // Works
return;
function abc(){}

Это функциональное выражение:

var xyz = function(){};

xyz здесь определяется с точки зрения назначения:

// We can't call it here
xyz(); // UNDEFINED!!!

// Now it is defined
xyz = function(){}

// We can call it here
xyz(); // works

Объявление функции и выражение функции - вот настоящая причина различия, продемонстрированного Грегом.

Интересный факт:

var xyz = function abc(){};
console.info(xyz.name); // Prints "abc"

Лично я предпочитаю объявление «выражение функции», потому что таким образом я могу контролировать видимость. Когда я определяю функцию типа

var abc = function(){};

Я знаю, что определил функцию локально. Когда я определяю функцию типа

abc = function(){};

Я знаю, что я определил его глобально, при условии, что я не определил abc где-либо в цепочке областей видимости. Этот стиль определения устойчив даже при использовании внутри eval(). Хотя определение

function abc(){};

зависит от контекста и может заставить вас гадать, где он на самом деле определен, особенно в случае eval() - ответ: это зависит от браузера.

В терминах информатики мы говорим об анонимных функциях и именованных функциях. Я думаю, что наиболее важным отличием является то, что анонимная функция не привязана к имени, отсюда и название анонимной функции. В JavaScript это объект первого класса, динамически объявляемый во время выполнения.

Дополнительные сведения об анонимных функциях и лямбда-исчислении можно найти в Википедии (http://en.wikipedia.org/wiki/Anonymous_function).

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

  • Независимо от места, где они заявлены (но все же ограничены по объему).
  • Более устойчив к ошибкам, таким как условная инициализация (при желании вы все еще можете переопределить).
  • Код становится более читабельным за счет выделения локальных функций отдельно от функций области видимости. Обычно в области видимости сначала идут функциональные возможности, а затем объявления локальных функций.
  • В отладчике вы четко увидите имя функции в стеке вызовов вместо «анонимной / оцененной» функции.

Я подозреваю, что за указанными функциями последуют и другие ПРОФИ. А то, что указано как преимущество именованных функций, является недостатком для анонимных.

Исторически анонимные функции возникли из-за неспособности JavaScript как языка перечислять элементы с именованными функциями:

{
    member:function() { /* How do I make "this.member" a named function? */
    }
}

Два фрагмента кода, которые вы разместили там, будут вести себя практически для всех целей одинаково.

Однако разница в поведении заключается в том, что в первом варианте (var functionOne = function() {}) эта функция может быть вызвана только после этого места в коде.

Во втором варианте (function functionTwo()) функция доступна для кода, который выполняется выше места объявления функции.

Это связано с тем, что в первом варианте функция назначается переменной foo во время выполнения. Во втором случае функция назначается этому идентификатору, foo, во время синтаксического анализа.

Дополнительная техническая информация

В JavaScript есть три способа определения функций.

  1. Ваш первый фрагмент показывает выражение функции. Это включает использование оператор "функции" для создания функции - результат этого оператора может быть сохранен в любой переменной или свойстве объекта. Таким образом, выражение функции является мощным. Выражение функции часто называют «анонимной функцией», потому что у него не обязательно должно быть имя,
  2. Ваш второй пример - объявление функции. Это использует оператор "функция" для создания функции. Функция становится доступной во время синтаксического анализа и может быть вызвана в любом месте этой области. Вы все еще можете сохранить его в переменной или свойстве объекта позже.
  3. Третий способ определения функции - это Конструктор "Function ()", который не показан в вашем исходном сообщении. Не рекомендуется использовать его, так как он работает так же, как eval(), у которого есть свои проблемы.

Говоря о глобальном контексте, оба оператора var и FunctionDeclaration в конце создадут свойство не подлежащий удалению для глобального объекта, но значение обоих можно перезаписать.

Тонкое различие между двумя способами заключается в том, что при запуске процесса Создание экземпляра переменной (до фактического выполнения кода) все идентификаторы, объявленные с помощью var, будут инициализированы с помощью undefined, а те, которые используются FunctionDeclaration, будут доступны с этого момента, например:

 alert(typeof foo); // 'function', it's already available
 alert(typeof bar); // 'undefined'
 function foo () {}
 var bar = function () {};
 alert(typeof bar); // 'function'

Назначение barFunctionExpression происходит до времени исполнения.

Глобальное свойство, созданное FunctionDeclaration, можно без проблем перезаписать, как и значение переменной, например:

 function test () {}
 test = null;

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

Что касается вашего отредактированного первого примера (foo = function() { alert('hello!'); };), это необъявленное назначение, я настоятельно рекомендую вам всегда использовать ключевое слово var.

При назначении без оператора var, если указанный идентификатор не найден в цепочке областей видимости, он станет свойством удаляемый глобального объекта.

Кроме того, необъявленные назначения бросают ReferenceError в ECMAScript 5 под Строгий режим.

Обязательно прочтите:

Примечание: Этот ответ был объединен с Другой вопрос, в котором основное сомнение и заблуждение со стороны OP заключалось в том, что идентификаторы, объявленные с помощью FunctionDeclaration, не могут быть перезаписаны, что не так.

Важная причина - добавить одну и только одну переменную в качестве «корня» вашего пространства имен ...

var MyNamespace = {}
MyNamespace.foo= function() {

}

или же

var MyNamespace = {
  foo: function() {
  },
  ...
}

Есть много техник для размещения имен. Это стало более важным с появлением множества доступных модулей JavaScript.

Также см. Как объявить пространство имен в JavaScript?

Другие комментаторы уже рассмотрели семантическую разницу двух приведенных выше вариантов. Хочу отметить стилистическое отличие: только вариант «присваивания» может задавать свойство другого объекта.

Я часто создаю модули JavaScript по такой схеме:

(function(){
    var exports = {};

    function privateUtil() {
            ...
    }

    exports.publicUtil = function() {
            ...
    };

    return exports;
})();

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

(Обратите также внимание на то, что присваивание должно требовать точки с запятой после оператора, а объявление запрещает это.)

@EugeneLazutkin дает пример, где он называет назначенную функцию для использования shortcut() как внутренняя ссылка на себя. Джон Ресиг приводит другой пример - копирование рекурсивной функции, назначенной другому объекту в своем руководстве Изучение продвинутого Javascript. Хотя назначение функций свойствам здесь не является строго вопросом, я рекомендую активно опробовать руководство - запустите код, нажав кнопку в правом верхнем углу, и дважды щелкните код, чтобы отредактировать его по своему вкусу.

Примеры из учебника: рекурсивные вызовы в yell():

Тесты терпят неудачу при удалении исходного объекта ниндзя. (стр. 13)

var ninja = { 
  yell: function(n){ 
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; 
  } 
}; 
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." ); 

var samurai = { yell: ninja.yell }; 
var ninja = null; 

try { 
  samurai.yell(4); 
} catch(e){ 
  assert( false, "Uh, this isn't good! Where'd ninja.yell go?" ); 
}

Если вы назовете функцию, которая будет вызываться рекурсивно, тесты пройдут. (стр. 14)

var ninja = { 
  yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
  } 
}; 
assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" ); 

var samurai = { yell: ninja.yell }; 
var ninja = {}; 
assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );

Еще одно отличие, которое не упоминается в других ответах, заключается в том, что если вы используете анонимную функцию

var functionOne = function() {
    // Some code
};

и используйте его как конструктор, как в

var one = new functionOne();

тогда one.constructor.name не определится. Function.name нестандартен, но поддерживается Firefox, Chrome, другими браузерами, производными от Webkit, и IE 9+.

С

function functionTwo() {
    // Some code
}
two = new functionTwo();

с помощью two.constructor.name можно получить имя конструктора в виде строки.

Я использую переменный подход в своем коде по очень конкретной причине, теория которой абстрактно описана выше, но пример может помочь некоторым людям, вроде меня, с ограниченным знанием JavaScript.

У меня есть код, который мне нужно запустить со 160 независимо разработанными брендами. Большая часть кода находится в общих файлах, но материалы, относящиеся к брендингу, находятся в отдельном файле, по одному для каждого бренда.

Некоторые бренды требуют определенных функций, а некоторые нет. Иногда мне приходится добавлять новые функции, чтобы делать новые вещи, связанные с брендом. Я рад изменить общий код, но я не хочу менять все 160 наборов файлов брендинга.

Используя синтаксис переменной, я могу объявить переменную (по сути, указатель на функцию) в общем коде и либо назначить тривиальную функцию-заглушку, либо установить значение null.

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

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

Первая (функция doSomething (x)) должна быть частью нотации объекта.

Второй (var doSomething = function(x){ alert(x);}) просто создает анонимную функцию и присваивает ее переменной doSomething. Итак, doSomething () вызовет функцию.

Возможно, вы захотите узнать, что такое объявление функции и выражение функции.

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

function foo() {
    return 3;
}

ECMA 5 (13.0) defines the syntax as
function Identifier ( FormalParameterListopt ) { FunctionBody }

В приведенном выше условии имя функции отображается в пределах ее области видимости и области ее родителя (в противном случае она была бы недоступна).

И в выражении функции

Выражение функции определяет функцию как часть более крупного синтаксиса выражения (обычно присваивания переменной). Функции, определенные через выражения функций, могут быть именованными или анонимными. Выражения функций не должны начинаться с слова «функция».

// Anonymous function expression
var a = function() {
    return 3;
}

// Named function expression
var a = function foo() {
    return 3;
}

// Self-invoking function expression
(function foo() {
    alert("hello!");
})();

ECMA 5 (13.0) defines the syntax as
function Identifieropt ( FormalParameterListopt ) { FunctionBody }

Объявление функции и выражение функции, присвоенное переменной, после установления привязки ведут себя одинаково.

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

По сути, все объявления функций и объявления переменных поднимаются в верхнюю часть функция, в котором происходит объявление (вот почему мы говорим, что JavaScript имеет объем функции).

  • Когда объявление функции поднимается, тело функции "следует" поэтому, когда тело функции оценивается, переменная немедленно быть привязанным к функциональному объекту.

  • Когда объявление переменной поднимается, инициализация выполняет нет следовать, но «оставлен позади». Переменная инициализируется как undefined в начале тела функции и будет назначенный значение в исходном месте кода. (Фактически, ему будет присвоено значение в том месте каждый, где происходит объявление переменной с тем же именем.)

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

Несколько примеров...

var foo = 1;
function bar() {
  if (!foo) {
    var foo = 10 }
  return foo; }
bar() // 10

Переменная foo поднимается на вершину функции, инициализируется как undefined, так что !foo - это true, поэтому foo назначается 10. foo вне сферы bar не играет никакой роли и остается нетронутым.

function f() {
  return a; 
  function a() {return 1}; 
  var a = 4;
  function a() {return 2}}
f()() // 2

function f() {
  return a;
  var a = 4;
  function a() {return 1};
  function a() {return 2}}
f()() // 2

Объявления функций имеют приоритет над объявлениями переменных, и последнее объявление функции «прилипает».

function f() {
  var a = 4;
  function a() {return 1}; 
  function a() {return 2}; 
  return a; }
f() // 4

В этом примере a инициализируется объектом функции, полученным в результате оценки второго объявления функции, а затем назначается 4.

var a = 1;
function b() {
  a = 10;
  return;
  function a() {}}
b();
a // 1

Здесь сначала поднимается объявление функции, объявляя и инициализируя переменную a. Далее этой переменной присваивается 10. Другими словами: присвоение не присваивается внешней переменной a.

Пример того, когда следует предпочесть первый метод второму, - это когда вам нужно избегать переопределения предыдущих определений функции.

С

if (condition){
    function myfunction(){
        // Some code
    }
}

, это определение myfunction переопределит любое предыдущее определение, так как оно будет выполнено во время синтаксического анализа.

Пока

if (condition){
    var myfunction = function (){
        // Some code
    }
}

выполняет правильную работу по определению myfunction, только когда встречается condition.

Если бы вы использовали эти функции для создания объектов, вы бы получили:

var objectOne = new functionOne();
console.info(objectOne.__proto__); // prints "Object {}" because constructor is an anonymous function

var objectTwo = new functionTwo();
console.info(objectTwo.__proto__); // prints "functionTwo {}" because constructor is a named function

Первый пример - это объявление функции:

function abc(){}

Второй пример - это выражение функции:

var abc = function() {};

Основное различие заключается в том, как они поднимаются (поднимаются и декларируются). В первом примере поднимается все объявление функции. Во втором примере поднимается только переменная 'abc', ее значение (функция) будет неопределенным, а сама функция останется в той позиции, в которой она была объявлена.

Проще говоря:

//this will work
abc(param);
function abc(){}

//this would fail
abc(param);
var abc = function() {}

Чтобы узнать больше об этой теме, я настоятельно рекомендую вам это связь

Лучшее объяснение Ответ Грега

functionTwo();
function functionTwo() {
}

Почему нет ошибки? Нас всегда учили, что выражения выполняются сверху вниз (??)

Потому что:

Function declarations and variable declarations are always moved (hoisted) invisibly to the top of their containing scope by the JavaScript interpreter. Function parameters and language-defined names are, obviously, already there. ben cherry

Это означает, что такой код:

functionOne();                  ---------------      var functionOne;
                                | is actually |      functionOne();
var functionOne = function(){   | interpreted |-->
};                              |    like     |      functionOne = function(){
                                ---------------      };

Обратите внимание на то, что часть объявлений, относящаяся к присваиванию, не была поднята. Поднято только имя.

Но в случае с объявлениями функций будет поднято все тело функции.:

functionTwo();              ---------------      function functionTwo() {
                            | is actually |      };
function functionTwo() {    | interpreted |-->
}                           |    like     |      functionTwo();
                            ---------------

В свете аргумента «именованные функции отображаются в трассировке стека» современные движки JavaScript на самом деле вполне способны представлять анонимные функции.

На момент написания этой статьи V8, SpiderMonkey, Chakra и Nitro всегда обращались к именованным функциям по их именам. Они почти всегда ссылаются на анонимную функцию по ее идентификатору, если он у нее есть.

SpiderMonkey может определить имя анонимной функции, возвращаемой другой функцией. Остальные не могут.

Если вы действительно, действительно хотите, чтобы ваш итератор и обратные вызовы успеха отображались в трассировке, вы также можете назвать их ...

[].forEach(function iterator() {});

Но по большей части не стоит переоценивать.

Ремень (Скрипка)

'use strict';

var a = function () {
    throw new Error();
},
    b = function b() {
        throw new Error();
    },
    c = function d() {
        throw new Error();
    },
    e = {
        f: a,
        g: b,
        h: c,
        i: function () {
            throw new Error();
        },
        j: function j() {
            throw new Error();
        },
        k: function l() {
            throw new Error();
        }
    },
    m = (function () {
        return function () {
            throw new Error();
        };
    }()),
    n = (function () {
        return function n() {
            throw new Error();
        };
    }()),
    o = (function () {
        return function p() {
            throw new Error();
        };
    }());

console.info([a, b, c].concat(Object.keys(e).reduce(function (values, key) {
    return values.concat(e[key]);
}, [])).concat([m, n, o]).reduce(function (logs, func) {

    try {
        func();
    } catch (error) {
        return logs.concat('func.name: ' + func.name + '\n' +
                           'Trace:\n' +
                           error.stack);
        // Need to manually log the error object in Nitro.
    }

}, []).join('\n\n'));

V8

func.name: 
Trace:
Error
    at a (http://localhost:8000/test.js:4:11)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: b
Trace:
Error
    at b (http://localhost:8000/test.js:7:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: d
Trace:
Error
    at d (http://localhost:8000/test.js:10:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: 
Trace:
Error
    at a (http://localhost:8000/test.js:4:11)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: b
Trace:
Error
    at b (http://localhost:8000/test.js:7:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: d
Trace:
Error
    at d (http://localhost:8000/test.js:10:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: 
Trace:
Error
    at e.i (http://localhost:8000/test.js:17:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: j
Trace:
Error
    at j (http://localhost:8000/test.js:20:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: l
Trace:
Error
    at l (http://localhost:8000/test.js:23:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: 
Trace:
Error
    at http://localhost:8000/test.js:28:19
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: n
Trace:
Error
    at n (http://localhost:8000/test.js:33:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: p
Trace:
Error
    at p (http://localhost:8000/test.js:38:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27 test.js:42

ПаукОбезьяна

func.name: 
Trace:
a@http://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: b
Trace:
b@http://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: d
Trace:
d@http://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
a@http://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: b
Trace:
b@http://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: d
Trace:
d@http://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
e.i@http://localhost:8000/test.js:17:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: j
Trace:
j@http://localhost:8000/test.js:20:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: l
Trace:
l@http://localhost:8000/test.js:23:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
m</<@http://localhost:8000/test.js:28:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: n
Trace:
n@http://localhost:8000/test.js:33:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: p
Trace:
p@http://localhost:8000/test.js:38:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1

Чакра

func.name: undefined
Trace:
Error
   at a (http://localhost:8000/test.js:4:5)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at b (http://localhost:8000/test.js:7:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at d (http://localhost:8000/test.js:10:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at a (http://localhost:8000/test.js:4:5)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at b (http://localhost:8000/test.js:7:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at d (http://localhost:8000/test.js:10:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at e.i (http://localhost:8000/test.js:17:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at j (http://localhost:8000/test.js:20:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at l (http://localhost:8000/test.js:23:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at Anonymous function (http://localhost:8000/test.js:28:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at n (http://localhost:8000/test.js:33:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at p (http://localhost:8000/test.js:38:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)

Нитро

func.name: 
Trace:
a@http://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: b
Trace:
b@http://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: d
Trace:
d@http://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: 
Trace:
a@http://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: b
Trace:
b@http://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: d
Trace:
d@http://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: 
Trace:
i@http://localhost:8000/test.js:17:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: j
Trace:
j@http://localhost:8000/test.js:20:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: l
Trace:
l@http://localhost:8000/test.js:23:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: 
Trace:
http://localhost:8000/test.js:28:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: n
Trace:
n@http://localhost:8000/test.js:33:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: p
Trace:
p@http://localhost:8000/test.js:38:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

Я добавляю свой ответ только потому, что все остальные тщательно рассмотрели подъемную часть.

Я долго думал о том, какой способ лучше, и благодаря http://jsperf.com теперь я знаю :)

Объявления функций быстрее, и это действительно важно в веб-разработке, верно? ;)

см. ответ о производительности ниже, разные результаты

d9k 01.03.2021 20:19

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

Ответ Грега достаточно хорош, но я все же хотел бы добавить к нему кое-что, что я только что узнал, просматривая видео Дуглас Крокфорд.

Выражение функции:

var foo = function foo() {};

Заявление о функции:

function foo() {};

Оператор функции - это просто сокращение для оператора var со значением function.

Так

function foo() {};

расширяется до

var foo = function foo() {};

Что расширяется дальше:

var foo = undefined;
foo = function foo() {};

И они оба поднялись на вершину кода.

Screenshot from video

Я перечисляю различия ниже:

  1. Объявление функции можно разместить в любом месте кода. Даже если он вызывается до того, как определение появляется в коде, он запускается, когда объявление функции фиксируется в памяти или поднимается, прежде чем любой другой код на странице начнет выполнение.

    Взгляните на функцию ниже:

    function outerFunction() {
        function foo() {
           return 1;
        }
        return foo();
        function foo() {
           return 2;
        }
    }
    alert(outerFunction()); // Displays 2
    

    Это потому, что во время выполнения это выглядит так: -

    function foo() {  // The first function declaration is moved to top
        return 1;
    }
    function foo() {  // The second function declaration is moved to top
        return 2;
    }
    function outerFunction() {
        return foo();
    }
    alert(outerFunction()); //So executing from top to bottom,
                            //the last foo() returns 2 which gets displayed
    

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

    Та же функция с использованием функциональных выражений:

    function outerFunction() {
        var foo = function() {
           return 1;
        }
        return foo();
        var foo = function() {
           return 2;
        }
    }
    alert(outerFunction()); // Displays 1
    

    Это потому, что во время выполнения это выглядит так:

    function outerFunction() {
       var foo = undefined;
       var foo = undefined;
    
       foo = function() {
          return 1;
       };
       return foo ();
       foo = function() {   // This function expression is not reachable
          return 2;
       };
    }
    alert(outerFunction()); // Displays 1
    
  2. Записывать объявления функций в нефункциональные блоки, такие как если, небезопасно, потому что они не будут доступны.

    if (test) {
        function x() { doSomething(); }
    }
    
  3. Выражение именованной функции, подобное приведенному ниже, может не работать в браузерах Internet Explorer до версии 9.

    var today = function today() {return new Date()}
    

Оба являются разными способами определения функции. Разница в том, как браузер интерпретирует и загружает их в контекст выполнения.

Первый случай - это функциональные выражения, которые загружаются только тогда, когда интерпретатор достигает этой строки кода. Поэтому, если вы сделаете это, как показано ниже, вы получите сообщение об ошибке functionOne не является функцией.

functionOne();
var functionOne = function() {
    // Some code
};

Причина в том, что в первой строке для functionOne не присваивается значение, и, следовательно, оно не определено. Мы пытаемся вызвать его как функцию и, следовательно, получаем ошибку.

Во второй строке мы присваиваем ссылку на анонимную функцию functionOne.

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

functionOne();
function functionOne() {
   // Some code
}

Подъем- это действие интерпретатора JavaScript по перемещению всех объявлений переменных и функций в верхнюю часть текущей области.

Однако поднимаются только фактические объявления. оставляя задания там, где они есть.

  • переменные / функции, объявленные внутри страницы, являются глобальными и могут получить доступ в любом месте этой страницы.
  • переменные / Функции, объявленные внутри функции, имеют локальную область видимости. означает, что они доступны / доступны внутри тела функции (области видимости), они недоступны вне тела функции.

Переменная

Javascript называется слабо типизированным языком. Это означает, что переменные Javascript могут содержать значение любого Тип данных. Javascript автоматически заботится об изменении типа переменной на основе значения / литерала, предоставленного во время выполнения.

global_Page = 10;                                               var global_Page;      « undefined
    « Integer literal, Number Type.   -------------------       global_Page = 10;     « Number         
global_Page = 'Yash';                 |   Interpreted   |       global_Page = 'Yash'; « String
    « String literal, String Type.    «       AS        «       global_Page = true;   « Boolean 
var global_Page = true;               |                 |       global_Page = function (){          « function
    « Boolean Type                    -------------------                 var local_functionblock;  « undefined
global_Page = function (){                                                local_functionblock = 777;« Number
    var local_functionblock = 777;                              };  
    // Assigning function as a data.
};  

Функция

function Identifier_opt ( FormalParameterList_opt ) { 
      FunctionBody | sequence of statements

      « return;  Default undefined
      « return 'some data';
}
  • функции, объявленные внутри страницы, поднимаются вверх страницы с глобальным доступом.
  • функции, объявленные внутри функционального блока, поднимаются наверх блока.
  • Возвращаемое значение функции по умолчанию - 'неопределенный', значение по умолчанию объявления Переменная также 'undefined'

    Scope with respect to function-block global. 
    Scope with respect to page undefined | not available.
    

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

function globalAccess() {                                  function globalAccess() {      
}                                  -------------------     }
globalAccess();                    |                 |     function globalAccess() { « Re-Defined / overridden.
localAccess();                     «   Hoisted  As   «         function localAccess() {
function globalAccess() {          |                 |         }
     localAccess();                -------------------         localAccess(); « function accessed with in globalAccess() only.
     function localAccess() {                              }
     }                                                     globalAccess();
}                                                          localAccess(); « ReferenceError as the function is not defined

Выражение функции

        10;                 « literal
       (10);                « Expression                (10).toString() -> '10'
var a;                      
    a = 10;                 « Expression var              a.toString()  -> '10'
(function invoke() {        « Expression Function
 console.info('Self Invoking');                      (function () {
});                                                               }) () -> 'Self Invoking'

var f; 
    f = function (){        « Expression var Function
    console.info('var Function');                                   f ()  -> 'var Function'
    };

Функция, присвоенная переменной Пример:

(function selfExecuting(){
    console.info('IIFE - Immediately-Invoked Function Expression');
}());

var anonymous = function (){
    console.info('anonymous function Expression');
};

var namedExpression = function for_InternalUSE(fact){
    if (fact === 1){
        return 1;
    }

    var localExpression = function(){
        console.info('Local to the parent Function Scope');
    };
    globalExpression = function(){ 
        console.info('creates a new global variable, then assigned this function.');
    };

    //return; //undefined.
    return fact * for_InternalUSE( fact - 1);   
};

namedExpression();
globalExpression();

javascript интерпретируется как

var anonymous;
var namedExpression;
var globalExpression;

anonymous = function (){
    console.info('anonymous function Expression');
};

namedExpression = function for_InternalUSE(fact){
    var localExpression;

    if (fact === 1){
        return 1;
    }
    localExpression = function(){
        console.info('Local to the parent Function Scope');
    };
    globalExpression = function(){ 
        console.info('creates a new global variable, then assigned this function.');
    };

    return fact * for_InternalUSE( fact - 1);    // DEFAULT UNDEFINED.
};

namedExpression(10);
globalExpression();

Вы можете проверить объявление функции, тест выражения в разных браузерах, используя jsperf Test Runner


Классы функций конструктора ES5: Функциональные объекты, созданные с помощью Function.prototype.bind

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

function Shape(id) { // Function Declaration
    this.id = id;
};
    // Adding a prototyped method to a function.
    Shape.prototype.getID = function () {
        return this.id;
    };
    Shape.prototype.setID = function ( id ) {
        this.id = id;
    };

var expFn = Shape; // Function Expression

var funObj = new Shape( ); // Function Object
funObj.hasOwnProperty('prototype'); // false
funObj.setID( 10 );
console.info( funObj.getID() ); // 10

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

ArrowFunction : ArrowParameters => ConciseBody.

const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; };
console.info( fn(2) ); // Even
console.info( fn(3) ); // Odd

new Function() можно использовать для передачи тела функции в виде строки. И, следовательно, это можно использовать для создания динамических функций. Также передача сценария без выполнения сценария.

var func = new Function("x", "y", "return x*y;");
function secondFunction(){
   var result;
   result = func(10,20);
   console.info ( result );
}

secondFunction()

Хотя это хорошо и верно, но какое именно это имеет отношение к задаваемому вопросу?

Jack Giffin 11.05.2018 00:06

В JavaScript есть два способа создания функций:

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

    function fn(){
      console.info("Hello");
    }
    fn();
    

    Это очень простой, не требующий пояснений, используемый во многих языках и стандартный для семейства языков C. Мы объявили функцию, определив ее, и выполнили ее, вызвав.

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

  2. Выражение функции:

    var fn=function(){
      console.info("Hello");
    }
    fn();
    

    В JavaScript есть первоклассные функции, то есть создание функции и присвоение ее переменной точно так же, как вы создаете строку или число и назначаете их переменной. Здесь переменной fn присвоена функция. Причина этой концепции в том, что функции являются объектами в JavaScript; fn указывает на экземпляр объекта вышеупомянутой функции. Мы инициализировали функцию и присвоили ее переменной. Он не выполняет функцию и не присваивает результат.

Ссылка: Синтаксис объявления функции JavaScript: var fn = function () {} vs function fn () {}

Они очень похожи с некоторыми небольшими отличиями, первая - это переменная, которая назначается анонимной функции (Объявление функции), а вторая - это нормальный способ создания функции в JavaScript (Объявление анонимной функции), оба имеют использование, минусы и плюсы :

1. Выражение функции

var functionOne = function() {
    // Some code
};

A Function Expression defines a function as a part of a larger expression syntax (typically a variable assignment ). Functions defined via Functions Expressions can be named or anonymous. Function Expressions must not start with “function” (hence the parentheses around the self invoking example below).

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

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

function functionTwo() {
    // Some code
}

A Function Declaration defines a named function variable without requiring variable assignment. Function Declarations occur as standalone constructs and cannot be nested within non-function blocks. It’s helpful to think of them as siblings of Variable Declarations. Just as Variable Declarations must start with “var”, Function Declarations must begin with “function”.

Это нормальный способ вызова функции в JavaScript, эта функция может быть вызвана еще до того, как вы ее объявите, как в JavaScript все функции получают подъем, но если у вас есть 'use strict', это не будет подъемным, как ожидалось, это хороший способ для вызова всех обычных функций, которые невелики по строкам и не являются функцией-конструктором.

Кроме того, если вам нужна дополнительная информация о том, как подъемник работает в JavaScript, перейдите по ссылке ниже:

https://developer.mozilla.org/en-US/docs/Glossary/Hoisting

О производительности:

Новые версии V8 представили несколько внутренних оптимизаций, как и SpiderMonkey.

Теперь почти нет разницы между выражением и объявлением.
Функциональное выражение кажется быстрее сейчас.

Хром 62.0.3202Chrome test

FireFox 55Firefox test

Хром Канарейка 63.0.3225Chrome Canary test


Anonymous function expressions appear to have better performance against Named function expression.


Fire FoxFirefox named_anonymousChrome CanaryChrome canary named_anonymousХромChrome named_anonymous

Различия в результатах слишком малы, чтобы их можно было рассматривать как разницу. Если вы запустите тест 100 раз, вы получите 100 результатов.

Ronny Sherer 14.10.2020 15:59

@RonnySherer, вы знакомы с jsperf? Тесты проводились после более чем 10 миллионов запусков!

Panos Kal. 14.10.2020 17:44

В каждом измерении есть помехи. Компьютер находится в другом состоянии, и это не единственный процесс, запущенный на компьютере. Когда разница настолько мала, это означает, что на нее нельзя полагаться, и это практически то же самое. Попробуйте выполнить тест на разумность 10 раз один за другим, и вы увидите, что цифры разные. Довольно близко, но не то же самое.

Ronny Sherer 18.10.2020 00:30

@RonnySherer js perf создает виртуальную среду специально для учета процессов с этими небольшими различиями. Он не запущен на моем компьютере. Работает только это. Когда что-то такое маленькое, может быть, кому-то наплевать. НО тем не менее я правильно считаю и сообщаю об этом. Если кто-то хочет использовать его внутри цикла с миллиардами итераций, ему следует выбрать функцию с наилучшей производительностью.

Panos Kal. 18.10.2020 16:09

Виртуальная среда находится на сервере, который может делать другие вещи. Я сделал несколько тестов. Результаты никогда не бывают одинаковыми.

Ronny Sherer 21.10.2020 17:54

Этот сайт был создан только для этого, поэтому можно с уверенностью предположить, что они сделали свою работу. Во всяком случае, пользователи SO могут предполагать все, что угодно. Я просто сообщаю результаты.

Panos Kal. 22.10.2020 11:14

Я предпочитаю определять функцию как переменную:

let first = function(x){
   return x[0];
}

Вместо:

function first(){
    ....
}

Потому что я могу использовать выражения и декораторы при определении функции. Например:

let safe = function(f){
  try {f()...}
}
let last = safe(function(x){return x[0]}).

Также с ES6 он намного короче:

 let last = x => x[0]
 ...........
 function last(x){
     return x[0];
 }
......

let last = safe(x => x[0]);

Выражение в JS: что-то, что возвращает значение
Пример: попробуйте следующее в консоли Chrome:

a = 10
output : 10

(1 + 3)
output = 4

Декларация / Заявление: что-то, что не возвращает значение
Пример:

if (1 > 2) {
 // do something. 
}

здесь (1> 2) - выражение, а выражение «если» - нет. Он ничего не возвращает.


Точно так же у нас есть объявление / оператор функции и выражение функции
Возьмем пример:

// test.js

var a = 10;

// function expression
var fun_expression = function() {
   console.info("Running function Expression");
}

// funciton expression

function fun_declaration() {
   console.info("Running function Statement");
}

Важный: Что происходит, когда движки JavaScript запускают указанный выше файл js.

  • Когда этот js запускается, произойдет следующее:

    1. В памяти будут созданы переменные 'a' и 'fun_expression'. И память будет создана для оператора функции fun_declaration.
    2. 'a' будет присвоено 'undefined'. 'fun_expression' будет присвоено 'undefined'. fun_declaration будет в памяти полностью.
      Примечание. Шаги 1 и 2 выше называются «Контекст выполнения - этап создания»..

Теперь предположим, что мы обновили js до.

// test.js

console.info(a)  //output: udefined (No error)
console.info(fun_expression)  // output: undefined (No error)
console.info(fun_expression()) // output: Error. As we trying to invoke undefined. 
console.info(fun_declaration()) // output: running function statement  (As fun_declaration is already hoisted in the memory). 

var a = 10;

// function expression
var fun_expression = function() {
   console.info('Running function expression')
}

// function declaration

function fun_declaration() {
   console.info('running function declaration')
}

console.info(a)   // output: 10
console.info(fun_expression()) //output: Running function expression
console.info(fun_declaration()) //output: running function declaration

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

Это называется функциональным выражением:

var getRectArea = function(width, height) {
    return width * height;
};

console.info("Area of Rectangle: " + getRectArea(3,4));
// This should return the following result in the console: 
// Area of Rectangle: 12

Это называется объявлением функции:

var w = 5;
var h = 6;

function RectArea(width, height) {  //declaring the function
  return area = width * height;
}                                   //note you do not need ; after }

RectArea(w,h);                      //calling or executing the function
console.info("Area of Rectangle: " + area);
// This should return the following result in the console: 
// Area of Rectangle: 30

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

Следует отметить один важный момент:

пусть есть две функции: -

sum(1,2);

const sum = function(first, second) {
  return first + second;
}

В приведенном выше случае это даст ошибку, что сумма не определена, но

sum(1,2);

function sum(first, second) {
  return first + second;
}

Эта функция не выдаст никаких ошибок, так как в этом случае будет иметь место Подъем.

Первый - это Выражение анонимной функции:

var functionOne = function() {
  // some code
};

А второй - Объявление функции:

function functionTwo () {
  // some code
}

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

Именованные функции против. Анонимные функции

Анонимную функцию набирать быстро и легко, и многие библиотеки и инструменты, как правило, поощряют этот идиоматический стиль кода. Однако у анонимных функций есть недостатки:

  • Анонимные функции Читаемость: пропускают имя, что может сделать код менее читаемым.

  • Анонимные функции Отладка: не имеют имени в трассировке стека, что может затруднить отладку.

  • Самостоятельная ссылка: что делать, если функции нужно ссылаться на себя, например, для рекурсии.

Выражение функции именования:

Предоставление имени для выражения функции довольно эффективно устраняет все эти недостатки и не имеет ощутимых недостатков. Лучше всего всегда называть выражения своей функции:

setTimeout(function timeHandler() { // <-- look, a name here!
  console.info("I've waited 1 second");
}, 1000);

Именование IIFE (выражение немедленного вызова функции):

(function IIFE(str) { // <-- look, always name IIFEs!
  console.info(str); // "Hello!"
})('Hello!');

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

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

   var functionOne = (function() {
      return {

         sayHello: function(){
                console.info('say hello')

         },
         redirectPage:function(_url){
                window.location.href = _url;
         }

      }
})();

У вас есть выбор, какую функцию вызывать. например, functionOne.sayHello или functionOne. redirectPage. А если вы вызовете functionTwo, будет выполнен весь блок кода.

Объявление функции разницы и выражение функции:

Javascript имеет первоклассные функции. Это означает, что их можно рассматривать как любую другую переменную. Функции могут быть переданы как аргументы функции, возвращены функцией и может храниться в переменных.

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

  1. Выражения функций могут быть анонимными, тогда как объявление функции должно иметь имя.
  2. У обоих есть свойство name, которое используется для идентификации функции. Свойство name выражения функции - это имя переменной, к которой оно привязано, тогда как имя объявления функции - это просто заданное имя.
  3. Объявления функций поднимаются, а выражения функций - нет. Поднимается только переменная, имеющая значение undefined.

Вот пример:

try {
  functionOne();
} catch (e) {
  console.info('i cant run because im not hoisted');
}

functionTwo();

// function expression, does not get hoisted
let functionOne = function randomName() {
    // Some code
};

// function declaration, gets hoisted
function functionTwo() {
   console.info('I get hoisted');
}

try {
  randomName(); // this isn't the proper name, it is functionOne
} catch (e) {
  console.info('You cant call me with randomName my name is function one');
}

:

var functionOne = function() {} определяет во время выполнения, а function functionTwo() {} определяет во время синтаксического анализа.

// Run-Time function declaration 
functionOne(); // Calling functionOne function here will give an Error
var functionOne = function () {
  // Some code
};

// Parse-Time function declaration 
functionTwo(); // Calling functionTwo function will not give an Error
function functionTwo() {
  // Some code...
}

Объяснение между временем выполнения и временем анализа время выполнения javascript и время разбора

Вы не можете использовать метод .bind() для объявлений функций, но можете использовать для выражений функций.

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

function x() {
  console.info(this)
}.bind('string')

x()

Выражение функции:

var x = function() {
  console.info(this)
}.bind('string')

x()

Другие вопросы по теме