Питання var functionName = function () {} vs function functionName () {}


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

Попередній розробник використовує два способи декларування функцій, і я не можу з'ясувати, чи є причини за нею.

Два способи:

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

Які причини для використання цих двох різних методів і які плюси і мінуси кожного? Чи є щось, що можна зробити за допомогою одного методу, який не може бути зроблено з іншим?


6059
2017-12-03 11:31


походження


permadi.com/tutorial/jsFunc/index.html це дуже хороша сторінка про функції JavaScript - uzay95
Це пов'язано відмінно стаття про Названі вирази функцій. - Phrogz
@ CMS посилається на цю статтю: kangax.github.com/nfe/#expr-vs-decl - Upperstage
Вам слід знати дві речі: # 1 У JavaScript, декларації підняті. Це означає, що var a = 1; var b = 2; стає var a; var b; a = 1; b = 2. Таким чином, коли ви оголошуєте функціюOne, вона оголошується, але його значення не встановлюється негайно. Оскільки, оскільки functionTwo - це просто декларація, вона потрапляє до вершини сфери. # 2 functionTwo дозволяє вам отримати доступ до властивості імені, що допомагає багато чого при спробі щось налагоджувати. - xavierm02
О, до речі, правильний синтаксис з ";" після призначення та без після декларації. Наприклад, function f(){} проти var f = function(){};. - xavierm02


Відповіді:


Різниця в цьому 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'S значення - якщо не use strict в дійсності, в цьому випадку це просто піднімає помилку.


4493
2017-12-03 11:37



@Greg: До речі, різниця не тільки в тому, що вони розбираються в різний час. По суті, ваш functionOneце просто змінна, яка має анонімну функцію, тоді як functionTwo це насправді названа функція. Зателефонувати .toString() на обох, щоб побачити різницю. Це важливо в деяких випадках, коли ви хочете отримати назву функції програмно. - Jason Bunting
Існують різні. Перший - це function expression другий - це function declaration. Ви можете прочитати тут докладніше: javascriptwebblog.wordpress.com/2010/07/06/... - Michal Kuklis
@Greg Частина вашої відповіді щодо часу розбору та часу виконання не є правильною. У JavaScript, декларації функцій не визначаються під час аналізу, але під час виконання. Процес відбувається так: вихідний код аналізується -> оцінюється програма JavaScript -> ініціалізується контекст глобального виконання -> виконується інстанція, що зв'язує декларацію. Під час цього процесу декларації функцій інсценируются (див. Крок 5 з Глава 10.5) - Šime Vidas
Термінологія цього явища називається підйомною. - Colin Pear
Ця відповідь не має нічого на Євгена. І це зовсім неправдоподібно до твердження про час розбору часу та часу виконання. - Griffin


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

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

По-друге, можна об'єднати обидва стилі:

var xyz = function abc(){};

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

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

Якщо ви хочете використовувати псевдоніми в усіх браузерах, використовуйте таку декларацію:

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

У цьому випадку обидва xyz і abc є псевдонімами одного і того ж об'єкта:

console.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() - відповідь: це залежить від браузера.


1805
2017-12-03 17:43



Я називаю RoBorg, але його ніде не можна знайти. Просто: RoBorg === Грег. Так історія може бути переписана в епоху Інтернету. ;-) - Eugene Lazutkin
var xyz = функція abc () (); console.log (xyz === abc); Усі веб-переглядачі, які я перевірив (Safari 4, Firefox 3.5.5, Opera 10.10) дає мені "Невизначена змінна: abc". - NVI
В цілому я думаю, що цей пост добре продемонстрував розбіжності та переваги використання декларації функцій. Я згоден погодитися не погодитися з вигодами від використання функцій вираження функції до змінної, особливо тому, що "вигода", схоже, є пропагандою оголошення глобального об'єкта ... і всі знають, що ви не повинні захаращувати глобальне поле імен , чи не так? ;-) - natlee75
Імo величезна причина використовувати названу функцію тому, що відладчики можуть використовувати ім'я, щоб допомогти вам зрозуміти ваш стіл зі списку дзвінків або трасування стеку. це смокче, коли ви подивіться на стек викликів і побачите "анонімну функцію" глибину 10 рівнів ... - goat
@Antimony Декларація функції не те ж саме, що і блок. Це слід пояснити краще: stackoverflow.com/questions/17409945/... - Cypher


Нижче перелічено стандартні форми, які створюють функції: (Спочатку написано для іншого питання, але адаптовано після переміщення в канонічне питання.)

Умови:

Швидкий список:

  • Декларація функцій

  • "Анонім" function Вираз (що, незважаючи на термін, іноді створює функції з іменами)

  • Названо function Вираз

  • Ініціалізатор функції доступу (ES5 +)

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

  • Декларація методу в ініціалізаторі об'єктів (ES2015 +)

  • Конструктор та Методичні декларації в Росії class (ES2015 +)

Декларація функцій

Перша форма - це декларація функції, який виглядає так:

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

Декларація функції є a декларація; це не висловлювання чи заява. Таким чином, ви не слідуєте цьому за допомогою ; (хоча це робить це нешкідливо).

Декларація функції обробляється, коли виконання входить у контекст, в якому він з'являється раніше виконується будь-який покроковий код. Функція, яку вона створює, називається власним ім'ям (x у наведеному вище прикладі), і це ім'я потрапляє в область, в якій з'являється декларація.

Оскільки він обробляється перед будь-яким покроковим кодом у тому самому контексті, ви можете виконати такі дії:

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

До ES2015 специфікація не покриває те, що повинен робити движок JavaScript, якщо ви внесете декларацію функцій у структуру керування типу try, if, switch, whileі т. д., як це:

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

І оскільки вони обробляються раніше Пошаговий код запускається, складно знати, що робити, коли вони знаходяться в контрольній структурі.

Хоча цього не було зазначено до ES2015, це був допустиме подовження підтримувати декларації функцій у блоках. На жаль (та неминуче), різні двигуни робили різні речі.

Станом на ES2015, специфікація говорить, що робити. Насправді це дає три окремі речі:

  1. Якщо в вільному режимі ні на веб-браузері, двигун JavaScript повинен робити одне
  2. Якщо в вільному режимі в веб-браузері, движок JavaScript повинен робити щось інше
  3. Якщо в строгий режим (браузер чи ні), движок 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's not in the same block)

"Анонім" function Вираз

Друга звичайна форма називається а вираз анонімної функції:

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

Як і всі вирази, вона оцінюється, коли вона досягається при послідовному виконанні коду.

У ES5 ця функція не має назви (вона анонімна). У ES2015 для функції присвоюється ім'я, якщо можливо, виводячи його з контексту. У наведеному вище прикладі ім'я буде y. Щось подібне зроблено, коли функція є значенням ініціалізатора ресурсу. (Докладніше про те, коли це трапляється, і правила, шукайте SetFunctionName в специфікація- здається повсюди місце.)

Названо function Вираз

Третя форма - це а названа функція вираження ("НФЕ"):

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() дзвонити Це функція.

Пара речей щодо функцій стрілки:

  1. У них немає власних this. Замість цього вони закрий в this контексту, де вони визначені. (Вони теж закриваються arguments і, де це доречно, super.) Це означає, що this всередині них таке ж, як і this де вони створені і не можуть бути змінені.

  2. Як ви помітили з вищевикладеного, ви не використовуєте ключове слово function; замість цього ви використовуєте =>.

The 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));

Версія без { ... } називається функцією стрілки з a орган вираження або лаконічне тіло. (Також: А. лаконічний функція стрілки.) Один з { ... } визначення тіла - це функція стрілки з 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.


544
2018-03-04 13:35



потім ім'я w просто ігнорується? - BiAiB
@PellePenna: назви функцій корисні для багатьох речей. Два biggies, на мій погляд, є рекурсією, а ім'я функції відображається в стеку викликів, слідів винятку та ін. - T.J. Crowder
Тепер це має бути прийнята відповідь. Це набагато останнім, ніж вищесказане. - Chaim Eliyah
@ChaimEliyah - "Прийняття не означає, що це найкраща відповідь, це просто означає, що він працював для того, хто запитував". джерело - ScrapCode
@ А.Р .: Цілком правда. Цікаво, правда, прямо над тим, що він говорить: "Найкращі відповіді з'являються спочатку, так що їх завжди легко знайти". Оскільки прийнята відповідь відображається в першу чергу навіть за більш високими оцінками голосування, тур може бути дещо суперечливим. ;-) Крім того, трохи неточно, якщо ми визначаємо "найкраще" за голосами (що не є надійним, то це саме те, що ми отримали), "найкращі" відповіді відображаються лише в першу чергу, якщо ви використовуєте вкладку "Голос" - інакше відповіді, які спочатку є, є активними або найстарішими. - T.J. Crowder


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

Тонка різниця між двома способами полягає в тому, що коли Змінна інстанція процес працює (до фактичного виконання коду) всі ідентифікатори, оголошені з var буде ініціалізовано з undefined, і ті, що використовуються FunctionDeclarationВона буде доступна з того моменту, наприклад:

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

Завдання bar  FunctionExpression відбувається до часу виконання.

Глобальна власність, створена a FunctionDeclaration можна перезаписати без будь-яких проблем, як значення змінної, наприклад:

 function test () {}
 test = null;

Інша очевидна різниця між вашими двома прикладами полягає в тому, що перша функція не має назви, але друга має його, що може бути дійсно корисним при налагодженні (наприклад, перевірці стеків викликів).

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

З призначенням, без var твердження, якщо посилання в ідентифікаторі не знайдено в ланцюжку масштабу, він стане a руйнується властивість глобального об'єкта.

Також незадекларовані завдання скидають а ReferenceError на ECMAScript 5 під Строгий режим.

Необхідно прочитати:

Примітка: Ця відповідь була об'єднана з інше питання, в якому основним сумнівом та неправильним розумінням ОП було те, що ідентифікатори оголошені а FunctionDeclaration, не можна переписати, що не так.


133
2017-08-08 19:32



Я не знав, що функції можна перезаписати в JavaScript! Крім того, такий порядок аналізу є для мене великим пунктом продажу. Я думаю, мені потрібно подивитися, як я створюю функції. - Xeoncross
+0 до статті "Вирази функцій імен", дефіцитована "стаття, як це 404. Можливе дзеркало ?: kangax.github.com/nfe - Mr_Chimp
@ CMS Красиво. Майте на увазі, хоча я ніколи не бачив оригіналу, тому я не знаю, чи це дзеркало, чи просто ще одна стаття з тим самим заголовком! - Mr_Chimp
@Mr_Chimp Я впевнений, що це, thewaybackmachine каже, що він отримав 302 під час сканування, і переспрямування було на посилання, яке ви надали. - John


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

Проте різниця у поведінці полягає в тому, що з першим варіантом (var functionOne = function() {}), цю функцію можна викликати тільки після того моменту в коді.

З другим варіантом (function functionTwo()), функція доступна для коду, який працює вище, де оголошується функція.

Це тому, що з першим варіантом ця функція призначена для змінної foo під час виконання По-друге, ця функція призначена для цього ідентифікатора foo, під час розбору.

Додаткова технічна інформація

JavaScript має три способи визначення функцій.

  1. Ваш перший фрагмент показує a функція вираження. Це передбачає використання оператор "функція" щоб створити функцію - результат цього оператора може бути збережений в будь-якому змінні або об'єкті властивості. Вираз функції є потужним таким чином. Вираз функції часто називають "анонімною функцією", тому що вона не повинна мати назви,
  2. Ваш другий приклад - це декларація функції. Це використовує "функція" твердження створити функцію. Ця функція доступна під час аналізу і може бути викликана в будь-якому місці цього масштабу. Ви все ще можете зберегти його в змінні або властивість об'єкта пізніше.
  3. Третій спосіб визначення функції - це "Функція ()" конструктор, який не відображається в оригіналі. Не рекомендується використовувати це, оскільки воно працює так само, як і в eval(), що має свої проблеми.

111
2018-04-20 04:54





Краще пояснення Грега відповідає

functionTwo();
function functionTwo() {
}

Чому не помиляється? Ми завжди вчили, що вирази виконуються зверху вниз (??)

Оскільки:

Функціональні декларації та декларації змінних завжди переносяться (hoisted) невидимо до вершини їхньої сфер, що використовується інтерпретатором JavaScript. Функціональні параметри та визначені мовою імена є, очевидно, вже там. бен вишня

Це означає, що код подібний до цього:

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

Зверніть увагу, що частина призначення декларацій не була піднята. Тільки ім'я піднято.

Але у випадку з функціональними деклараціями буде також піднімано ціле тіло функції:

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

91
2017-08-09 02:45



HI suhail дякую за ясну інформацію про тему функції. Тепер моє запитання: яка буде першою декларацією в ієрархії декларації, чи є декларація змінної (functionOne) або функція декларації (functionTwo)? - Sharathi RB


Інші commenters вже охопили семантичну різницю двох варіантів вище. Я хотів відзначити стилістичну різницю: лише варіант "assignment" може встановити властивість іншого об'єкта.

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

(function(){
    var exports = {};

    function privateUtil() {
            ...
    }

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

    return exports;
})();

З цією схемою ваші загальнодоступні функції будуть використовувати завдання, а ваші приватні функції використовують декларацію.

(Зверніть також увагу на те, що призначення після призначення має вимагати крапку з комою, тоді як декларація забороняє це.)


83
2018-03-03 19:19



yuiblog.com/blog/2007/06/12/module-pattern є первинним посиланням на модельний модуль, наскільки я можу сказати. (Хоча ця стаття використовує var foo = function(){...} Синтаксис навіть для приватних змінних. - Sean McMillan
Насправді це не цілком вірно в деяких старих версіях IE. (function window.onload() {} була річ.) - Ry-♦


Ілюстрація того, коли віддати перевагу першому методу другому, є, коли потрібно уникнути перевизначення попередніх визначень функції.

З

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

, це визначення myfunction перевищить будь-яке попереднє визначення, оскільки це буде зроблено під час аналізу.

Поки

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

правильно визначає роботу myfunction тільки коли condition зустрічається


68
2018-03-29 13:26



цей приклад хороший і близький до досконалості, але його можна покращити. найкращий приклад буде визначений var myFunc = null; поза межами циклу або поза блоком if / elseif / else. Потім ви можете умовно призначити різні функції однієї змінної. У JS, це краще згоди, щоб призначити відсутнє значення для нуля, а потім до undefined. Тому ви повинні оголосити myFunction як нуль першим, а потім призначити його пізніше, умовно. - Alexander Mills


Важливою причиною є додавання однієї і єдиної змінної як "Root" вашого простору імен ...

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

}

або

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

Існує багато методів визначення назв. Це стає ще важливішим завдяки безлічі доступних модулів JavaScript.

Також див Як я можу оголосити простір імен в JavaScript?


55
2017-08-08 19:44



Здається, ця відповідь була об'єднана в це питання з іншого питання та формулювання може здавалося б, трохи не пов'язані з це питання Ви хочете редагувати відповідь, і, здається, вона більше спрямована саме на це питання? (для повторення: це не зовсім ваша вина ... лише побічний ефект об'єднаного питання). Ви також можете його видалити, і я думаю, що ви збережете свою репутацію. Або ви можете залишити це; оскільки він старий, він може не мати великої різниці. - Andrew Barber


Підйомник  це дія інтерпретатора JavaScript для переміщення всіх змінних і функціональних декларацій у верхню частину поточного об'єму. 

Однак лише фактичні декларації підняті. залишаючи завдання, де вони знаходяться.

  • Змінні та функції, оголошені всередині сторінки, можуть отримати доступ до будь-якої сторінки цієї сторінки.
  • Змінні / Функції, оголошені всередині функції, мають локальний обсяг. означає, що вони доступні / доступні всередині тіла функції (область роботи), вони не доступні поза тілом функції.

Змінна

Javascript називається вільно набраною мовою. Це означає, що змінні Javascript можуть зберігати значення будь-якого Тип даних. Javascript автоматично дбає про зміну типу змінної на підставі значення / літерного, наданого під час виконання.

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

Функція

function Identifier_opt ( FormalParameterList_opt ) { 
      FunctionBody | sequence of statements

      « return;  Default undefined
      « return 'some data';
}
  • Функції, оголошені всередині сторінки, піднімаються до верхньої частини сторінки, що має глобальний доступ.
  • функції, оголошені всередині функціонального блоку, піднімаються до верхньої частини блоку.
  • За замовчуванням повертається значення функції "невизначено', Змінна значення за замовчуванням також 'undefined'

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

Декларація функцій

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

Вираження функції

        10;                 « literal
       (10);                « Expression                (10).toString() -> '10'
var a;                      
    a = 10;                 « Expression var              a.toString()  -> '10'
(function invoke() {        « Expression Function
 console.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
2018-01-25 14:46



ахм, твоя відповідь ... чи не це неоднозначне? добре написано, хоча так +1, витрачати і писати занадто багато інформації. - Danish