Каковы наилучшие методы определения функций в JavaScript? [Дубликат]

Вы должны взглянуть на Remoting

6176
задан Richard Garside 22 March 2017 в 14:24
поделиться

28 ответов

  • 1
    @Greg: Кстати, разница заключается не только в том, что они разбираются в разное время. По сути, ваш functionOne - это просто переменная с назначенной ей анонимной функцией, тогда как functionTwo - фактически именованная функция. Вызовите .toString() на обоих, чтобы увидеть разницу. Это важно в некоторых случаях, когда вы хотите получить имя функции программно. – Jason Bunting 5 August 2011 в 22:18
  • 2
  • 3
    Есть и разные. Первый - function expression, второй - function declaration. Вы можете прочитать больше по этой теме: javascriptweblog.wordpress.com/2010/07/06/… – Michal Kuklis 14 November 2011 в 08:03
  • 4
    @Greg. Часть вашего ответа, касающаяся времени синтаксиса и времени выполнения, неверна. В JavaScript объявления функций не определены во время разбора, а во время выполнения. Процесс выполняется следующим образом: Исходный код разобран - & gt; Программа JavaScript оценивается - & gt; Глобальный контекст выполнения инициализируется - & gt; выполняется реализация привязки привязки. Во время этого процесса создаются экземпляры функций (см. Шаг 5 из , глава 10.5 ). – Šime Vidas 4 January 2012 в 02:59
  • 5
    Терминология этого явления известна как подъем. – Colin Pear 3 January 2013 в 09:22
  • 6
    Этот ответ ничего не имеет о Евгении. И это довольно вводит в заблуждение с помощью команды parse-time vs run-time. – Griffin 18 July 2013 в 10:45

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

1. Функция Expression

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

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

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

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

function functionTwo() {
    // Some code
}

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

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

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

https://developer.mozilla.org/en-US/docs / Глоссарий / Подъемно

68
ответ дан Alireza 16 August 2018 в 01:55
поделиться
  • 1
    этот пример хорош и близок к совершенству, но может быть улучшен. лучшим примером может быть определение var myFunc = null; вне цикла или вне блока if / elseif / else. Затем вы можете условно назначить разные функции одной и той же переменной. В JS лучше назначить отсутствующее значение null, а затем не определено. Поэтому сначала следует объявить myFunction как null, а затем назначить его позже, условно. – Alexander Mills 26 May 2015 в 20:31
  • 2
    ...also this way of declaring is a better way to create Constructor functions in JavaScript, пожалуйста, уточните, мне любопытно! – Karl Morrison 13 June 2017 в 12:44
  • 3
    Одна из причин заключается в том, что все встроенные функции Constructor в JavaScript, созданные как эта функция Number () {[native code]}, и вы не должны путаться со встроенными, также в этом случае более безопасно, и вы заканчиваете вверх, но не используя подъем ... – Alireza 13 June 2017 в 12:56

@EugeneLazutkin дает пример, где он называет назначенную функцию, чтобы иметь возможность использовать shortcut() как внутреннюю ссылку на себя. Джон Ресиг дает другой пример - копирование рекурсивной функции, назначенной другому объекту в его учебном пособии Learning Advanced 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." );
134
ответ дан Community 16 August 2018 в 01:55
поделиться
  • 1
    Я не знал, что функции могут быть перезаписаны в JavaScript! Кроме того, этот порядок разбора является большой точкой продажи для меня. Наверное, мне нужно посмотреть, как я создаю функции. – Xeoncross 8 August 2010 в 20:43
  • 2
    +0 к выражению функции «Имена функций», демистифицированному » статья, поскольку это 404ing. Возможное зеркало ?: kangax.github.com/nfe – Mr_Chimp 29 November 2011 в 17:10
  • 3
    @CMS Ницца. Имейте в виду, хотя я никогда не видел оригинала, поэтому я не знаю, если это зеркало или еще одна статья с тем же названием! – Mr_Chimp 29 November 2011 в 17:25
  • 4
    @Mr_Chimp Я уверен, что это так, thewaybackmachine говорит, что он получил 302 при сканировании, а перенаправление было на ссылку, которую вы предоставили. – John 30 January 2012 в 17:18
  • 5
    Просто вызов this.yell работает тоже :) – Ry-♦ 21 April 2013 в 21:54
  • 6
    Похоже, что этот ответ был объединен с этим вопросом из другого вопроса, и формулировка может казалась крошечным битом, не связанным с вопросом this . Не могли бы вы отредактировать ответ, чтобы он, скорее, был более конкретно направлен на этот вопрос? (повторить, это не ваша вина вообще ... просто побочный эффект объединенного вопроса). Вы также можете удалить его, и я думаю, что вы сохранили бы свою репутацию. Или вы можете оставить его; поскольку он старый, это может не иметь большого значения. – Andrew Barber 29 May 2013 в 22:13
  • 7
    Извините, но это неправильно - я не знаю, что Крокфорд пытается сказать в этом слайде. Обе функции & amp; объявления переменных всегда поднимаются вверх до их объема. Разница заключается в том, что назначения переменных (независимо от того, назначаете ли вы его строкой, логическим или функцией), не поднимаются вверх, а тела функций (с использованием объявления функции). – Thomas Heymann 5 October 2015 в 16:25
  • 8
    Взгляните на эти примеры кода: gist.github.com/cyberthom/36603fbc20de8e04fd09 – Thomas Heymann 5 October 2015 в 16:51
  • 9
    HI suhail благодарит за четкую информацию о теме функции. Теперь мой вопрос: каким будет первое объявление в иерархии объявлений, будь то объявление переменной (functionOne) или объявление функции (functionTwo)? – Sharathi RB 2 February 2016 в 13:09

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

Однако существует , как и , когда объект функции фактически связан с его переменной. Это различие связано с механизмом, называемым изменением подъема в 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 16 August 2018 в 01:55
поделиться
  • 1
    У вас есть немного странный способ разместить закрывающие фигурные скобки. Вы кодер Python? Похоже, вы пытаетесь сделать Javascript похожим на Python. Я боюсь, что это путает других людей. Если бы мне пришлось поддерживать ваш JavaScript-код, я бы сначала разрешил ваш код через автоматический prettyprinter. – nalply 14 May 2013 в 13:46
  • 2
    Отличная почта. «Самоисполняемая функция» или «сразу вызываемое выражение функции» должна быть достаточно легкой, чтобы видеть, и его предпочтение в стиле не должно умалять его пост - это точно и точно суммирует «подъем». +1 – Ricalsin 17 December 2013 в 20:13

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

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.

14
ответ дан Ingo Kegel 16 August 2018 в 01:55
поделиться
  • 1
    Имя в первом случае не будет определено, поскольку его функция анонимная назначена переменной. Я думаю, что слово анонимное было изобретено для вещей, для которых не определено их имя :) – Om Shankar 17 January 2013 в 08:13
  • 2
    В этом примере два = new становятся глобальной функцией, потому что нет var – Waqas 29 August 2015 в 05:04

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

  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. (function) .name

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

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 === "");

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

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 может быть несколько разметок компиляции Microsecond 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;
    }
}

  • Функция стрелки с 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;
    }
})();

7
ответ дан Jack Giffin 16 August 2018 в 01:55
поделиться

В свете аргумента «названные функции отображаются в стеках» аргументы, современные механизмы 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

Чакра

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 16 August 2018 в 01:55
поделиться

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

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

enter image description here [/g1]

Объявление функций происходит быстрее, и это то, что действительно имеет значение в web dev right ? ;)

34
ответ дан Leon Gaban 16 August 2018 в 01:55
поделиться
  • 1
    Я бы сказал, что ремонтопригодность является наиболее важным аспектом большинства кодов. Производительность важна, но в большинстве случаев IO скорее всего станет более узким местом, чем вы определяете свои функции. Однако есть некоторые проблемы, когда вам нужен каждый бит производительности, который вы можете получить, и это полезно в этих случаях. Также хорошо иметь ответ здесь, который четко отвечает четко определенной части вопроса. – Richard Garside 2 May 2015 в 15:22
  • 2
    Ну, я нашел, что это будет другим способом с Firefox. jsperf.com/sandytest – Sandeep Nayak 17 November 2015 в 15:15
  • 3
    Микрообъекты всегда терпят неудачу. Глядя на jsperf.com - это потеря времени. Вам действительно нужно посмотреть исходный код JS-движка, официальную документацию или, по крайней мере, sniff dev blogs или списки рассылки. – gavenkoa 10 January 2016 в 16:13
  • 4
    Просто обновление, так как теперь я начал работать с полным функциональным стилем программирования в JavaScript, я никогда не использую объявления, а только выражения функций, чтобы я мог цепочки и вызывать свои функции по их именам переменных. Отъезд RamdaJS ... – Leon Gaban 28 December 2016 в 17:56
  • 5
    @SandeepNayak Я просто запускаю собственный тест в Firefox 50.0.0 / Windows 7 0.0.0, и на самом деле это так же, как у Леона. Поэтому, если ваш тест верен, я бы пришел к выводу, что тесты jsperf не являются ориентировочными, и все зависит от версии вашего браузера и / или ОС, или в конкретном состоянии текущего компьютера в этот конкретный момент. – ocramot 10 January 2017 в 14:40

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

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

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

var xyz = function abc(){};

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

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 & nbsp; Explorer). В основном, когда вы определяете функцию типа

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

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

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

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

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

// 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

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

Забавный факт:

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

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

var abc = function(){};

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

abc = function(){};

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

function abc(){};

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

1809
ответ дан Merlin 16 August 2018 в 01:55
поделиться
  • 1
    Я имею в виду RoBorg, но его нигде не найти. Простой: RoBorg === Грег. Вот как история может быть переписана в эпоху Интернета. ;-) – Eugene Lazutkin 26 July 2009 в 03:52
  • 2
    var xyz = function abc () {}; console.log (xyz === abc); Все браузеры, которые я тестировал (Safari 4, Firefox 3.5.5, Opera 10.10), дают мне «Неопределенная переменная: abc». – NVI 3 December 2009 в 18:43
  • 3
    В целом я думаю, что этот пост хорошо справляется с объяснением различий и преимуществ использования объявления функции. Я соглашусь не согласиться с тем, что преимущества использования назначений выражения функций для переменной, особенно с тех пор, как «выгоды» кажется, является призывом объявить глобальную сущность ... и все знают, что вы не должны загромождать глобальное пространство имен, верно? ;-) – natlee75 8 October 2013 в 17:30
  • 4
    ИМО - огромная причина использовать именованную функцию, потому что отладчики могут использовать это имя, чтобы помочь вам понять стек стека вызовов или трассировку стека. это отстой, когда вы смотрите на стек вызовов и видите «анонимную функцию». 10 уровней глубины ... – goat 26 January 2014 в 20:25
  • 5
    @Antimony Объявление функции - это не то же самое, что блок. Это должно объяснить лучше: stackoverflow.com/questions/17409945/… – Cypher 28 March 2014 в 01:25

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

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

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

Chrome 62.0.3202

FireFox 55

Chrome Canary 63.0.3225

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

Firefox Chrome Canary Chrome

7
ответ дан Panos Kal. 16 August 2018 в 01:55
поделиться
  • 1
    Да, эта разница настолько незначительна, что, надеюсь, разработчики будут заботиться о том, какой подход более удобен для удовлетворения своих конкретных потребностей, а не быстрее (вы получите разные результаты jsperf при каждой попытке в зависимости от что делает браузер - большинство задач javascript не должны заботиться о микро-оптимизации в этой степени). – squidbe 26 November 2017 в 02:41
  • 2
    @squidbe Нет никакой разницы. Смотрите здесь: jsperf.com/empty-tests-performance – Jack Giffin 10 May 2018 в 21:10

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

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 16 August 2018 в 01:55
поделиться
  • 1
    Я не могу воспроизвести это. console.log(objectOne.__proto__); печатает & quot; functionOne {} & quot; в моей консоли. Любые идеи, почему это может быть так? – Mike 22 March 2015 в 11:06
  • 2
    Я тоже не могу воспроизвести его. – daremkd 21 January 2016 в 16:57
  • 3
    Это возможность вашего отладчика (для отображения «класса» зарегистрированного объекта), и большинство из них могут вывести имя даже для анонимных выражений функций в наши дни. Кстати, вы должны четко указать, что между этими двумя экземплярами нет функциональной разницы. – Bergi 21 January 2016 в 17:26

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

111
ответ дан Peter Mortensen 16 August 2018 в 01:55
поделиться
  • 1
    Есть тест, подтверждающий: blog.firsov.net/2010/01/… Тест производительности JS - область действия и названные функции - Analytics – Sasha Firsov 4 February 2010 в 01:45
  • 2
    @Arjun В чем проблема, если вопрос был задан несколько лет назад? Ответ не только приносит пользу OP, но и потенциально всем пользователям SO, независимо от того, когда был задан вопрос. И что не так с ответом на вопросы, которые уже имеют принятый ответ? – SantiBailors 5 October 2015 в 12:58
  • 3
    @Arjun вы должны понять ответы на старые вопросы не плохо. Если бы это было так, у SO был бы такой барьер. Представьте, что в API есть изменения (хотя и не в контексте этого вопроса), и кто-то видит это и дает ответ с новым API, не следует ли это допускать? До тех пор, пока ответ не будет иметь смысла и не будет здесь, он будет автоматически опущен и удален. Вам не нужно беспокоиться об этом !!!! – Sudhansu Choudhary 18 October 2015 в 21:37
  • 4
    как насчет третьего варианта, var fn = function fn() {...}? – chharvey 20 August 2016 в 00:40
  • 5
    Привет Чхарви, не уверенный в вопросе ур, я думаю, что речь идет о выражении функции, о котором я уже говорил. Однако, если все же есть некоторая путаница, просто быть более сложной. – Anoop Rai 23 August 2016 в 10:00
  • 6
    да, я спрашивал о выражении функции named . он похож на ваш вариант № 2, за исключением того, что функция имеет идентификатор. обычно этот идентификатор совпадает с переменной, к которой он привязан, но это не всегда так. – chharvey 23 August 2016 в 10:39
  • 7
    Да Именованное выражение функции похоже на мою опцию # 2. Ну, наличие идентификатора не является обязательным, поскольку оно не используется. Всякий раз, когда вы будете выполнять выражение функции, вы будете использовать переменную, содержащую объект функции. Идентификатор не имеет никакой цели. – Anoop Rai 23 August 2016 в 11:42
  • 8
    Пожалуйста, уточните и предоставите фрагменты рабочего кода – Jack Giffin 10 May 2018 в 21:06

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

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

83
ответ дан ROMANIA_engineer 16 August 2018 в 01:55
поделиться
  • 1
    yuiblog.com/blog/2007/06/12/module-pattern - это первичная ссылка для шаблона модуля, насколько я могу судить. (Хотя в этой статье используется синтаксис var foo = function(){...} даже для частных переменных. – Sean McMillan 3 June 2011 в 13:32
  • 2
    На самом деле это не совсем верно в некоторых старых версиях IE. (function window.onload() {} был чем-то.) – Ry-♦ 21 April 2013 в 20:42

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

function abc(){}

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

var abc = function() {};

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

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

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

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

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

27
ответ дан sla55er 16 August 2018 в 01:55
поделиться
  • 1
    Ваш пример похож на верхний ответ – GôTô 5 June 2014 в 09:34
  • 2
    Основная причина для публикации этого ответа заключалась в том, чтобы предоставить ссылку внизу. Это была часть, которая мне не хватало, чтобы полностью понять вышеупомянутый вопрос. – sla55er 8 June 2014 в 06:44
  • 3
    Очень круто, что вы хотели поделиться ссылкой. Но ссылки на дополнительную информацию, в формате SO, должны просто быть комментарием ни о вопросе, ни в вашем любимом ответе. Очень необоснованно загромождать длинную сложную страницу, подобную этой, с повторной информацией, просто чтобы добавить одну полезную ссылку в конце ее. Нет, вы не получите очков за предоставление ссылки, но вы будете помогать сообществу. – XML 13 January 2015 в 01:26
546
ответ дан T.J. Crowder 16 August 2018 в 01:55
поделиться

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

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

secondFunction()
3
ответ дан Vikram S 16 August 2018 в 01:55
поделиться
  • 1
    Хотя это хорошо и верно, как именно это относится только к заданному вопросу? – Jack Giffin 10 May 2018 в 21:06

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

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

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

Переменная

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

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';
}
  • Функция

    function Identifier_opt ( FormalParameterList_opt ) { 
          FunctionBody | sequence of statements
    
          « return;  Default undefined
          « return 'some data';
    }
    
    • ], объявленные внутри страницы, поднимаются на верх страницы, имеющей глобальный доступ.
    • Функции
    • , объявленные внутри функционального блока, поднимаются на вершину блока.
    • Возвращаемое по умолчанию значение function is [ undefined ', Значение переменной по умолчанию , также «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
    

    Функция Expression

            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 рассматривает функции как объекты первого класса, поэтому, будучи объектом, вы можете назначить pro

    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 16 August 2018 в 01:55
поделиться
  • 1
    ahm, ваш ответ ... разве это не двусмысленно? хорошо написано, хотя так +1 для расходов и написания слишком много информации. – Danish 31 January 2016 в 18:56

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

С помощью

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

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

Хотя

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

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

68
ответ дан Alireza 16 August 2018 в 01:55
поделиться
  • 1
    этот пример хорош и близок к совершенству, но может быть улучшен. лучшим примером может быть определение var myFunc = null; вне цикла или вне блока if / elseif / else. Затем вы можете условно назначить разные функции одной и той же переменной. В JS лучше назначить отсутствующее значение null, а затем не определено. Поэтому сначала следует объявить myFunction как null, а затем назначить его позже, условно. – Alexander Mills 26 May 2015 в 20:31
  • 1
    Я не знал, что функции могут быть перезаписаны в JavaScript! Кроме того, этот порядок разбора является большой точкой продажи для меня. Наверное, мне нужно посмотреть, как я создаю функции. – Xeoncross 8 August 2010 в 20:43
  • 2
    +0 к выражению функции «Имена функций», демистифицированному » статья, поскольку это 404ing. Возможное зеркало ?: kangax.github.com/nfe – Mr_Chimp 29 November 2011 в 17:10
  • 3
    @CMS Ницца. Имейте в виду, хотя я никогда не видел оригинала, поэтому я не знаю, если это зеркало или еще одна статья с тем же названием! – Mr_Chimp 29 November 2011 в 17:25
  • 4
    @Mr_Chimp Я уверен, что это так, thewaybackmachine говорит, что он получил 302 при сканировании, а перенаправление было на ссылку, которую вы предоставили. – John 30 January 2012 в 17:18
  • 5
    Похоже, что этот ответ был объединен с этим вопросом из другого вопроса, и формулировка может казалась крошечным битом, не связанным с вопросом this . Не могли бы вы отредактировать ответ, чтобы он, скорее, был более конкретно направлен на этот вопрос? (повторить, это не ваша вина вообще ... просто побочный эффект объединенного вопроса). Вы также можете удалить его, и я думаю, что вы сохранили бы свою репутацию. Или вы можете оставить его; поскольку он старый, это может не иметь большого значения. – Andrew Barber 29 May 2013 в 22:13
  • 6
    Извините, но это неправильно - я не знаю, что Крокфорд пытается сказать в этом слайде. Обе функции & amp; объявления переменных всегда поднимаются вверх до их объема. Разница заключается в том, что назначения переменных (независимо от того, назначаете ли вы его строкой, логическим или функцией), не поднимаются вверх, а тела функций (с использованием объявления функции). – Thomas Heymann 5 October 2015 в 16:25
  • 7
    Взгляните на эти примеры кода: gist.github.com/cyberthom/36603fbc20de8e04fd09 – Thomas Heymann 5 October 2015 в 16:51
  • 8
    HI suhail благодарит за четкую информацию о теме функции. Теперь мой вопрос: каким будет первое объявление в иерархии объявлений, будь то объявление переменной (functionOne) или объявление функции (functionTwo)? – Sharathi RB 2 February 2016 в 13:09

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

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

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

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

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

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

functionOne();
function functionOne() {
   // Some code
}
111
ответ дан Peter Mortensen 16 August 2018 в 01:55
поделиться
  • 1
    Есть тест, подтверждающий: blog.firsov.net/2010/01/… Тест производительности JS - область действия и названные функции - Analytics – Sasha Firsov 4 February 2010 в 01:45
  • 2
    @Arjun В чем проблема, если вопрос был задан несколько лет назад? Ответ не только приносит пользу OP, но и потенциально всем пользователям SO, независимо от того, когда был задан вопрос. И что не так с ответом на вопросы, которые уже имеют принятый ответ? – SantiBailors 5 October 2015 в 12:58
  • 3
    @Arjun вы должны понять ответы на старые вопросы не плохо. Если бы это было так, у SO был бы такой барьер. Представьте, что в API есть изменения (хотя и не в контексте этого вопроса), и кто-то видит это и дает ответ с новым API, не следует ли это допускать? До тех пор, пока ответ не будет иметь смысла и не будет здесь, он будет автоматически опущен и удален. Вам не нужно беспокоиться об этом !!!! – Sudhansu Choudhary 18 October 2015 в 21:37
  • 4
    как насчет третьего варианта, var fn = function fn() {...}? – chharvey 20 August 2016 в 00:40
  • 5
    Привет Чхарви, не уверенный в вопросе ур, я думаю, что речь идет о выражении функции, о котором я уже говорил. Однако, если все же есть некоторая путаница, просто быть более сложной. – Anoop Rai 23 August 2016 в 10:00
  • 6
    да, я спрашивал о выражении функции named . он похож на ваш вариант № 2, за исключением того, что функция имеет идентификатор. обычно этот идентификатор совпадает с переменной, к которой он привязан, но это не всегда так. – chharvey 23 August 2016 в 10:39
  • 7
    Да Именованное выражение функции похоже на мою опцию # 2. Ну, наличие идентификатора не является обязательным, поскольку оно не используется. Всякий раз, когда вы будете выполнять выражение функции, вы будете использовать переменную, содержащую объект функции. Идентификатор не имеет никакой цели. – Anoop Rai 23 August 2016 в 11:42

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

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

(function(){
    var exports = {};

    function privateUtil() {
            ...
    }

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

    return exports;
})();

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

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

83
ответ дан ROMANIA_engineer 16 August 2018 в 01:55
поделиться
  • 1
    yuiblog.com/blog/2007/06/12/module-pattern - это первичная ссылка для шаблона модуля, насколько я могу судить. (Хотя в этой статье используется синтаксис var foo = function(){...} даже для частных переменных. – Sean McMillan 3 June 2011 в 13:32
  • 2
    На самом деле это не совсем верно в некоторых старых версиях IE. (function window.onload() {} был чем-то.) – Ry-♦ 21 April 2013 в 20:42
134
ответ дан Community 6 September 2018 в 01:12
поделиться
112
ответ дан Peter Mortensen 6 September 2018 в 01:12
поделиться
134
ответ дан Community 6 September 2018 в 01:12
поделиться
112
ответ дан Peter Mortensen 6 September 2018 в 01:12
поделиться
135
ответ дан Community 29 October 2018 в 07:54
поделиться
114
ответ дан Peter Mortensen 29 October 2018 в 07:54
поделиться
114
ответ дан Peter Mortensen 29 October 2018 в 07:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: