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

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

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

Два способа:

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

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

6012
задан Richard Garside 03 дек. '08 в 14:31
источник поделиться

32 ответов

  • 1
  • 2

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

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

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

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

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

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

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

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

if (test) {
   // Error or misbehavior
   function functionThree() { doSomething(); }
}

Вышеописанное фактически определяет functionThree независимо от test значения - если только не use strict действие, и в этом случае он просто вызывает ошибку.

4469
ответ дан Greg 03 дек. '08 в 14:37
источник поделиться

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

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

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

var xyz = function abc(){};

xyz будет определяться как обычно, abc - undefined во всех браузерах, но 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.log(xyz === abc); // prints "true"

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

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

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

var abc = function(){};
console.log(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.log(xyz.name); // Prints "abc"

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

var abc = function(){};

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

abc = function(){};

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

function abc(){};

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

1792
ответ дан Eugene Lazutkin 03 дек. '08 в 20:43
источник поделиться

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

Условия:

Быстрый список:

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

  • "Анонимный" function Выражение (которое, несмотря на термин, иногда создает функции с именами)

  • Именованный function Выражение

  • Инициализатор функции доступа (ES5 +)

  • Выражение функции Arrow (ES2015 +) (которое, как и анонимные выражения функций, не включает явное имя и все же может создавать функции с именами)

  • Объявление метода в Инициализаторе объектов (ES2015 +)

  • Объявления конструктора и метода в class (ES2015 +)

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

Первая форма - это объявление функции, которое выглядит следующим образом:

function x() {
    console.log('x');
}

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

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

Поскольку он обрабатывается до пошагового кода в том же контексте, вы можете делать такие вещи:

x(); // Works even though it above the declaration
function x() {
    console.log('x');
}

До ES2015 спецификация не охватывала то, что должен сделать движок JavaScript, если вы поместите объявление функции внутри структуры управления, например try, if, switch, while и т.д., например

if (someCondition) {
    function foo() {    // <===== HERE THERE
    }                   // <===== BE DRAGONS
}

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

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

Как и в ES2015, спецификация говорит, что делать. Фактически, это дает три отдельные вещи:

  • Если в свободном режиме не в веб-браузере, движок JavaScript должен сделать что-то одно.
  • Если в свободном режиме в веб-браузере движок JavaScript должен сделать что-то еще
  • Если в строгом режиме (браузер или нет), движок JavaScript должен сделать еще одну вещь

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

"use strict";
if (someCondition) {
    foo();               // Works just fine
    function foo() {
    }
}
console.log(typeof foo); // "undefined" (`foo` is not in scope here
                         // because it not in the same block)

"Анонимный" function Выражение

Вторая общая форма называется анонимным выражением функции:

var y = function () {
    console.log('y');
};

Как и все выражения, он оценивал, когда он достиг пошагового выполнения кода.

В ES5 созданная функция не имеет имени (анонимно). В ES2015 функции присваивается имя, если это возможно, вызывая его из контекста. В приведенном выше примере имя будет y. Нечто похожее делается, когда функция является значением инициализатора свойства. (Подробнее о том, когда это происходит, и правилах, найдите SetFunctionName в спецификация — она появляется повсюду. )

Именованный function Выражение

Третья форма - это именованное функциональное выражение ( "NFE" ):

var z = function w() {
    console.log('zw')
};

В этом случае функция, которая создается, имеет собственное имя (w). Как и все выражения, это оценивается, когда оно достигается при пошаговом выполнении кода. Имя функции не добавляется в область видимости; имя находится в пределах самой функции:

var z = function w() {
    console.log(typeof w); // "function"
};
console.log(typeof w);     // "undefined"

Обратите внимание, что NFE часто являются источником ошибок для реализаций JavaScript. IE8 и ранее, например, обрабатывают NFEs полностью неправильно, создавая две разные функции в два разных раза. У ранних версий Safari были проблемы. Хорошей новостью является то, что текущие версии браузеров (IE9 и выше, текущий Safari) больше не имеют этих проблем. (Но, к сожалению, IE8 по-прежнему широко используется, поэтому использование NFE с кодом для Интернета в целом все еще проблематично.)

Инициализатор функции доступа (ES5 +)

Иногда функции могут незаметно прокрадываться; что случай с функциями доступа. Вот пример:

var obj = {
    value: 0,
    get f() {
        return this.value;
    },
    set f(v) {
        this.value = v;
    }
};
console.log(obj.f);         // 0
console.log(typeof obj.f);  // "number"

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

Вы также можете создавать функции доступа с помощью Object.defineProperty, Object.defineProperties, а младший второй аргумент - Object.create.

Выражение функции стрелки (ES2015 +)

ES2015 приносит нам функцию стрелки. Вот один пример:

var a = [1, 2, 3];
var b = a.map(n => n * 2);
console.log(b.join(", ")); // 2, 4, 6

Смотрите, что n => n * 2 вещь скрывается в вызове map()? Это функция.

Несколько вещей о функциях стрелок:

  • У них нет собственных this. Вместо этого они закрывают this контекста, где они определены. (Они также закрываются над arguments и, при необходимости, super.) Это означает, что this внутри них совпадает с this, где они созданы, и не может быть изменен.

  • Как вы заметили выше, вы не используете ключевое слово function; вместо этого вы используете =>.

Приведенный выше пример n => n * 2 является одним из них. Если у вас есть несколько аргументов для передачи функции, вы используете parens:

var a = [1, 2, 3];
var b = a.map((n, i) => n * i);
console.log(b.join(", ")); // 0, 2, 6

(Помните, что Array#map передает запись как первый аргумент, а индекс - второй.)

В обоих случаях тело функции является просто выражением; возвращаемое значение функции будет автоматически результатом этого выражения (вы не используете явный return).

Если вы делаете больше, чем просто одно выражение, используйте {} и явный return (если вам нужно вернуть значение), как обычно:

var a = [
  {first: "Joe", last: "Bloggs"},
  {first: "Albert", last: "Bloggs"},
  {first: "Mary", last: "Albright"}
];
a = a.sort((a, b) => {
  var rv = a.last.localeCompare(b.last);
  if (rv === 0) {
    rv = a.first.localeCompare(b.first);
  }
  return rv;
});
console.log(JSON.stringify(a));

Версия без { ... } называется функцией стрелки с телом выражения или сжатым телом. (Также: краткая функция стрелки.) Тот, у кого { ... }, определяющий тело, является функцией стрелки с телом функции. (Также: подробная функция стрелки.)

Объявление метода в инициализаторе объектов (ES2015 +)

ES2015 разрешает более короткую форму объявления свойства, которое ссылается на функцию; это выглядит так:

var o = {
    foo() {
    }
};

эквивалент в ES5 и ранее был бы:

var o = {
    foo: function foo() {
    }
};

Объявления конструктора и метода в class (ES2015 +)

ES2015 приносит нам class синтаксис, включая объявленные конструкторы и методы:

class Person {
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    getFullName() {
        return this.firstName + " " + this.lastName;
    }
}

Есть два объявления функций выше: один для конструктора, который получает имя Person и один для getFullName, который является функцией, назначенной Person.prototype.

539
ответ дан T.J. Crowder 04 марта '14 в 16:35
источник поделиться

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

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

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

Назначение bar FunctionExpression выполняется до выполнения.

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

 function test () {}
 test = null;

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

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

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

Кроме того, необъявленные задания бросают ReferenceError на ECMAScript 5 в Strict Mode.

A должен читать:

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

130
ответ дан CMS 08 авг. '10 в 22:32
источник поделиться

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

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

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

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

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

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

  • В вашем первом фрагменте показано выражение функции. Это связано с использованием оператора "function" для создания функции - результат этого оператора может быть сохранен в любой переменной или объекте. Выражение функции является таким мощным. Выражение функции часто называют "анонимной функцией", поскольку оно не должно иметь имени,
  • Второй пример - объявление функции . Для создания функции используется оператор "function". Функция предоставляется во время разбора и может быть вызвана в любом месте этой области. Вы можете сохранить его позже в переменной или объекте.
  • Третий способ определения функции - конструктор "Function()" , который не показан в исходном сообщении. Не рекомендуется использовать это, поскольку он работает так же, как eval(), у которого есть свои проблемы.
109
ответ дан thomasrutter 20 апр. '10 в 7:54
источник поделиться

Лучшее объяснение Greg answer

functionTwo();
function functionTwo() {
}

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

Потому что:

Объявления функций и объявления переменных всегда перемещаются (hoisted) невидимо в верхнюю часть своей области с помощью интерпретатора JavaScript. Функциональные параметры и языковые имена, очевидно, уже есть. 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();
                            ---------------
90
ответ дан suhailvs 09 авг. '14 в 5:45
источник поделиться

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

Я часто создаю модули JavaScript с таким шаблоном:

(function(){
    var exports = {};

    function privateUtil() {
            ...
    }

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

    return exports;
})();

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

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

83
ответ дан Sean McMillan 03 марта '11 в 22:19
источник поделиться

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

С

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

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

В то время как

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

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

68
ответ дан Mbengue Assane 29 марта '13 в 16:26
источник поделиться

Важной причиной является добавление одной и только одной переменной в качестве "корня" вашего пространства имен...

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

}

или

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

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

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

55
ответ дан Rob 08 авг. '10 в 22:44
источник поделиться

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

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

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

Variable

Javascript называется свободно типизированным языком. Это означает, что переменные Javascript могут содержать значение любого Data-Type. 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 ', Variable значение по умолчанию объявления также '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.log('Self Invoking');                      (function () {
});                                                               }) () -> 'Self Invoking'

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

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

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

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

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

    var localExpression = function(){
        console.log('Local to the parent Function Scope');
    };
    globalExpression = function(){ 
        console.log('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.log('anonymous function Expression');
};

namedExpression = function for_InternalUSE(fact){
    var localExpression;

    if(fact === 1){
        return 1;
    }
    localExpression = function(){
        console.log('Local to the parent Function Scope');
    };
    globalExpression = function(){ 
        console.log('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.log( funObj.getID() ); // 10

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

ArrowFunction : ArrowParameters => ConciseBody.

const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; };
console.log( fn(2) ); // Even
console.log( fn(3) ); // Odd
47
ответ дан Yash 25 янв. '16 в 17:46
источник поделиться

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

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

enter image description here

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

33
ответ дан Leon Gaban 01 мая '15 в 18:06
источник поделиться

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

Однако существует разница в том, как и когда объект функции фактически связан с его переменной. Это различие связано с механизмом, называемым переменным подъемом в 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.

30
ответ дан eljenso 06 февр. '13 в 19:29
источник поделиться

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

function abc(){}

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

var abc = function() {};

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

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

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

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

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

27
ответ дан sla55er 05 июня '14 в 11:28
источник поделиться

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

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

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

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

{
    member:function() { /* How do I make "this.member" a named function? */
    }
}
25
ответ дан Sasha Firsov 23 янв. '10 в 23:32
источник поделиться

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

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

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

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

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

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

22
ответ дан Herc 29 нояб. '12 в 14:28
источник поделиться

Greg Answer достаточно хорош, но я все еще хотел бы добавить что-то к нему, что я узнал только сейчас, наблюдая видео Дугласа Крокфорда.

Функциональное выражение:

var foo = function foo() {};

Оператор функции:

function foo() {};

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

Итак,

function foo() {};

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

var foo = function foo() {};

Расширяется далее:

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

И они оба подняты в верхней части кода.

Screenshot from video

19
ответ дан Rohan 21 июля '15 в 10:45
источник поделиться

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

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

19
ответ дан Kafka 18 дек. '08 в 22:30
источник поделиться

@EugeneLazutkin дает пример, где он называет назначенную функцию, чтобы иметь возможность использовать shortcut() как внутренняя ссылка на себя. John Resig дает еще один пример - копирование рекурсивной функции, назначенной другому объекту в Изучение расширенного 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." );
16
ответ дан Joel Purra 04 авг. '12 в 18:24
источник поделиться

Я перечисляю следующие различия:

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

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

    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
    

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

    Те же функции, что и функциональные выражения:

    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
    
  • Нельзя записывать объявления функций в не-функциональных блоках, например , если, потому что они не будут доступны.

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

    var today = function today() {return new Date()}
    
13
ответ дан varna 09 сент. '15 в 13:30
источник поделиться

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

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

var objectTwo = new functionTwo();
console.log(objectTwo.__proto__); // prints "functionTwo {}" because constructor is a named function
13
ответ дан Pawel Furmaniak 25 окт. '13 в 19:38
источник поделиться

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

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.

13
ответ дан Ingo Kegel 15 окт. '12 в 13:42
источник поделиться

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

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

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

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

function foo() {
    return 3;
}

ECMA 5 (13.0) определяет синтаксис как
Идентификатор функции (FormalParameterList opt) {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) определяет синтаксис как
Идентификатор функции opt (FormalParameterList opt) {FunctionBody}

12
ответ дан NullPoiиteя 05 янв. '13 в 21:37
источник поделиться

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

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

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

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

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

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

Жгут проводов (Fiddle)

'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.log([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

SpiderMonkey

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

Chakra

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
10
ответ дан Jackson 12 окт. '14 в 3:58
источник поделиться

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

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

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

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

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

  • Функциональное выражение:

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

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

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

9
ответ дан Anoop Rai 14 авг. '16 в 12:13
источник поделиться

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

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

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

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

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

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

functionOne();
function functionOne() {
   // Some code
}
7
ответ дан Nitin9791 28 дек. '16 в 23:18
источник поделиться

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

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

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

Chrome 62.0.3202 Тест Chrome

FireFox 55 Firefox test

Chrome Canary 63.0.3225 Хелловерный тест


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


Firefox Firefox named_anonymous Chrome Canary Chrome canary named_anonymous Chrome Chrome named_anonymous

7
ответ дан Panos Kal. 28 сент. '17 в 7:34
источник поделиться

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

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

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

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

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

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

function functionTwo() {
    // Some code
}

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

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

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

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

6
ответ дан Alireza 09 мая '17 в 16:56
источник поделиться

Существует три примечательных сравнения между двумя различными декларациями функций, перечисленными ниже.

  1. Доступность (область действия) функции

Следующее работает, потому что function add() привязана к ближайшему блоку:

try {
  console.log("Success: ", add(1, 1));
} catch(e) {
  console.log("ERROR: " + e);
}

function add(a, b){
  return a + b;
}

Не работает следующее (потому что var add= superseeds function add()).

try {
  console.log("Success: ", add(1, 1));
} catch(e) {
  console.log("ERROR: " + e);
}

var add=function add(a, b){
  return a + b;
}

Следующие не работают, потому что add объявляется после его использования.

try {
  console.log("Success: ", add(1, 1));
} catch(e) {
  console.log("ERROR: " + e);
}

var add=function(a, b){
  return a + b;
}
  1. (Функция).name

Имя функции function thefuncname(){} является именем funcname, когда оно объявлено таким образом.

function foobar(a, b){}

console.log(foobar.name);

var a = function foobar(){};

console.log(a.name);

В противном случае, если функция объявлена как function(){}, функция.name является первой переменной, используемой для хранения функции.

var a = function(){};
var b = (function(){ return function(){} });

console.log(a.name);
console.log(b.name);

Если для этой функции нет переменных, то имя функции - это пустая строка ("").

console.log((function(){}).name === "");

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

var a = function(){};
var b = a;
var c = b;

console.log(a.name);
console.log(b.name);
console.log(c.name);
  1. Представление

В Google V8 и Firefox Spidermonkey может быть несколько микросекундных разностей JIST-компиляции, но в итоге результат будет таким же. Чтобы это доказать, давайте рассмотрим эффективность JSPerf в microbenchmarks, сравнив скорость двух фрагментов кода. Тесты JSPerf найдены здесь. И здесь найдены тесты jsben.ch. Как вы можете видеть, есть заметная разница, когда их не должно быть. Если вы действительно такой урод, как я, то это может стоить больше, пытаясь уменьшить количество переменных и функций в области действия и особенно устранять полиморфизм (например, использовать одну и ту же переменную для хранения двух разных типов).

Что такое "ближайший блок"

"Ближайший блок" - ближайшая "функция" (включая асинхронные функции, функции генератора и асинхронные функции генератора). Однако, интересно, function functionName() {} ведет себя как var functionName = function() {} когда в блоке не замыкания на элементы вне указанного закрытия. Обратите внимание.

  • Обычный var add=function(){}

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}');
  }
} catch(e) {
  console.log("Is a block");
}
var add=function(a, b){return a + b}
  • Обычная function add(){}

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
function add(a, b){
  return a + b;
}
  • функция

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(function () {
    function add(a, b){
      return a + b;
    }
})();
  • Заявление (например, if, else, for, while, try/catch/finally, switch, do/while, with)

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
{
    function add(a, b){
      return a + b;
    }
}
  • Arrow Функция с var add=function()

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(() => {
    var add=function(a, b){
      return a + b;
    }
})();
  • Функция Arrow С function add()

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(() => {
    function add(a, b){
      return a + b;
    }
})();
6
ответ дан Jack Giffin 15 янв. '18 в 4:55
источник поделиться

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

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

secondFunction()
3
ответ дан Vikram 10 мая '16 в 10:05
источник поделиться

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

3
ответ дан Tao 24 июня '15 в 13:08
источник поделиться
  • 1
  • 2

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