У JavaScript, коли ви хочете використовувати це:
(function(){
//Bunch of code...
})();
над цим:
//Bunch of code...
У JavaScript, коли ви хочете використовувати це:
(function(){
//Bunch of code...
})();
над цим:
//Bunch of code...
Відповіді:
Вся справа в змінному масштабі. Змінні, оголошені у функції самовиконання, за замовчуванням доступні лише для кодування в межах функції самовиконання. Це дозволяє писати код без побоювання того, як названі змінні в інших блоках коду JavaScript.
Наприклад, як згадується в коментарі Олександра :
(function() {
var foo = 3;
console.log(foo);
})();
console.log(foo);
Це спочатку увійде в журнал, 3
а потім видасть помилку на наступному, console.log
оскільки foo
не визначено.
var
, як це: ...function(){ foo=3;}
? Це встановило б глобальну змінну, правда?
function(){ var foo = 3; alert(foo); }; alert(foo);
Тому я все одно не отримую цього
Спрощений. Це дуже нормальний вигляд, його майже втішне:
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
Однак що робити, якщо я включу на свою сторінку дійсно зручну бібліотеку javascript, яка переводить розширені символи в їх представлення на базовому рівні?
Чекати, що?
Я маю на увазі, якщо хтось набирає персонажа з якимось акцентом на ньому, але я хочу лише "англійських" символів AZ у своїй програмі? Ну ... іспанські символи "ñ" та французькі "é" можуть бути переведені в основні символи "n" і "e".
Тож хтось приємний чоловік написав там всебічний конвертер символів, який я можу включити на свій сайт ... Я включаю його.
Одна проблема: у ній є функція, яка називається "ім'я", як і моя функція.
Це те, що називається зіткненням. У нас є дві функції, оголошені в тій самій області з тим же ім'ям. Ми хочемо цього уникнути.
Тому нам потрібно якось обшивати наш код.
Єдиний спосіб застосування коду в javascript - це вбудувати його у функцію:
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
Це може вирішити нашу проблему. Все тепер укладено і отримати доступ до нього можна лише з нашої дужки відкриття та закриття.
У нас є функція у функції ... що дивно дивитися, але цілком законно.
Лише одна проблема. Наш код не працює. Наша змінна userName ніколи не повторюється в консолі!
Ми можемо вирішити цю проблему, додавши виклик до нашої функції після наявного блоку коду ...
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
main();
Або раніше!
main();
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
Побічна проблема: Які шанси, що назва "головний" ще не використовується? ... так дуже, дуже струнка.
Нам потрібно БІЛЬШЕ масштабування. І якийсь спосіб автоматично виконати нашу основну () функцію.
Тепер ми переходимо до функцій автоматичного виконання (або самовиконання, самостійного запуску, будь-чого).
((){})();
Синтаксис незручний як гріх. Однак це працює.
Коли ви загортаєте визначення функції в дужки та включаєте список параметрів (інший набір чи круглі дужки!), Він виконує функцію виклику функції .
Тож давайте переглянемо наш код ще раз із деяким синтаксисом, що виконує себе:
(function main() {
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
)();
Отже, у більшості прочитаних вами навчальних посібників ви зараз будете бомбардувати терміном "анонімне самовиконання" чи чимось подібним.
Після багатьох років професійного розвитку настійно закликаю вас назвати кожну функцію, яку ви пишете для налагодження.
Коли щось піде не так (і це станеться), ви будете перевіряти відстань у своєму браузері. Це завжди легше скоротити ваші питання коду під час запису в трасуванні стека мають імена!
Величезна довговільна і сподіваюся, що це допоможе!
:)
Самовикликання (також відоме як автоматичне виклик) - це коли функція виконується негайно після її визначення. Це основний зразок і служить основою для багатьох інших моделей розвитку JavaScript.
Я великий шанувальник :), тому що:
Приємно - (Чому варто сказати, що це добре?)
Більше тут .
Розміщення імен. Області JavaScript є функціональними.
Я не можу повірити, що жодна з відповідей не згадує загальносвітові глобали.
(function(){})()
Конструкція не захищає від маються на увазі глобал, що для мене це більше занепокоєння, см http://yuiblog.com/blog/2006/06/01/global-domination/
В основному функціональний блок гарантує, що всі залежні "глобальні зміни", які ви визначили, обмежені вашою програмою, але це не захищає вас від визначення неявних глобалів. JSHint або подібне може надати рекомендації щодо захисту від такої поведінки.
Більш стислий var App = {}
синтаксис забезпечує аналогічний рівень захисту, і він може бути зафіксований у функціональному блоці на сторінках "public". (див. Ember.js або SproutCore для реальних прикладів бібліотек, які використовують цю конструкцію)
Що стосується private
властивостей, вони є завищеними, якщо ви не створюєте загальнодоступні рамки чи бібліотеку, але якщо вам потрібно їх реалізувати, Дуглас Крокфорд має кілька хороших ідей.
Я прочитав усі відповіді, чогось дуже важливого не вистачає . Є дві основні причини, чому мені потрібні самовиконання анонімних функцій, або, краще сказати, " Виявлення негайно викликаних функцій (IIFE) ":
Перший був дуже добре пояснений. Для другого, будь ласка, вивчіть наступний приклад:
var MyClosureObject = (function (){
var MyName = 'Michael Jackson RIP';
return {
getMyName: function () { return MyName;},
setMyName: function (name) { MyName = name}
}
}());
Увага 1: Ми не призначаємо функцію MyClosureObject
, а ще більше результат виклику цієї функції . Будьте в курсі()
в останньому рядку.
Увага 2: Що ви додатково повинні знати про функції в Javascript, це те, що внутрішні функції отримують доступ до параметрів і змінних функцій, вони визначені в межах.
Спробуємо кілька експериментів:
Я можу MyName
використати, getMyName
і це працює:
console.log(MyClosureObject.getMyName());
// Michael Jackson RIP
Такий винахідливий підхід не спрацює:
console.log(MyClosureObject.MyName);
// undefined
Але я можу встановити інше ім’я та отримати очікуваний результат:
MyClosureObject.setMyName('George Michael RIP');
console.log(MyClosureObject.getMyName());
// George Michael RIP
Редагувати: У наведеному вище прикладі MyClosureObject
призначено використовуватись без new
префікса, тому за умовою він не повинен бути використаний з великої літери.
Чи є параметр і "Пучок коду" повертає функцію?
var a = function(x) { return function() { document.write(x); } }(something);
Закриття. Значення something
отримує використання функції, призначеної для a
. something
може мати певне значення (для циклу) і кожен раз, коли функція a має нову функцію.
var x = something;
зовнішню функцію над x
параметром, однак: imo, це читабельніше таким чином ...
x
і будете залежати безпосередньо від лексичної сфери, тобто document.write(something)
...
Ізоляція сфери, можливо. Так що змінні всередині декларації функції не забруднюють зовнішній простір імен.
Звичайно, на половині реалізацій JS вони все одно будуть.
Ось вагомий приклад того, як самовикликання анонімної функції може бути корисним.
for( var i = 0; i < 10; i++ ) {
setTimeout(function(){
console.log(i)
})
}
Вихід: 10, 10, 10, 10, 10...
for( var i = 0; i < 10; i++ ) {
(function(num){
setTimeout(function(){
console.log(num)
})
})(i)
}
Вихід: 0, 1, 2, 3, 4...
let
замість var
першого випадку буде добре.
Оскільки функції в Javascript є першокласним об'єктом, визначаючи його таким чином, він ефективно визначає "клас", як C ++ або C #.
Ця функція може визначати локальні змінні та мати в ній функції. Внутрішні функції (ефективні методи екземплярів) матимуть доступ до локальних змінних (фактично змінні екземпляри), але вони будуть ізольовані від решти сценарію.
Функція самовиклику в JavaScript:
Самовикликаючий вираз викликається (запускається) автоматично, без виклику. Самовикликаючий вираз викликається відразу після його створення. Це в основному використовується для уникнення конфліктування імен, а також для досягнення інкапсуляції. Змінні або оголошені об'єкти недоступні за межами цієї функції. Щоб уникнути проблем мінімізації (filename.min) завжди використовуйте функцію, яка виконується самостійно.
Функція самовиконання використовується для управління областю змінної.
Область змінної - це область вашої програми, в якій вона визначена.
Глобальна змінна має глобальний масштаб; він визначений скрізь у вашому коді JavaScript і до нього можна отримати доступ з будь-якого місця в сценарії, навіть у ваших функціях. З іншого боку, змінні, оголошені в межах функції, визначаються лише в тілі функції. Вони є локальними змінними, мають локальну область застосування і до них можна отримати доступ лише в межах цієї функції. Параметри функції також враховуються як локальні змінні та визначаються лише в тілі функції.
Як показано нижче, ви можете отримати доступ до змінної глобальної змінної всередині своєї функції, а також зазначити, що в тілі функції локальна змінна має перевагу над глобальною змінною з тим самим іменем.
var globalvar = "globalvar"; // this var can be accessed anywhere within the script
function scope() {
alert(globalvar);
localvar = "localvar" //can only be accessed within the function scope
}
scope();
Таким чином, функція самовиконання дозволяє писати код без занепокоєння, як називаються змінні в інших блоках коду javascript.
(function(){
var foo = {
name: 'bob'
};
console.log(foo.name); // bob
})();
console.log(foo.name); // Reference error
Власне, вищевказана функція буде розглядатися як вираз функції без імені.
Основна мета обгортання функції з близькими та відкритими дужками - уникнути забруднення глобального простору.
Змінні та функції всередині виразу функції стали приватними (тобто) вони не будуть доступні поза функцією.
Коротка відповідь: запобігання забрудненню глобальної (або вищої) сфери застосування.
IIFE (негайно викликані функції виразів) - найкраща практика для написання скриптів як плагінів, доповнень, сценаріїв користувачів або будь-яких інших сценаріїв, які очікуються для роботи зі сценаріями інших людей. . Це гарантує, що будь-яка вказана вами змінна не надає небажаних ефектів на інші сценарії.
Це інший спосіб написання виразу IIFE. Я особисто віддаю перевагу такому методу:
void function() {
console.log('boo!');
// expected output: "boo!"
}();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
З наведеного вище прикладу ясно, що IIFE також може вплинути на ефективність та продуктивність, тому що функція, яка, як очікується, буде виконуватися лише один раз, буде виконана один раз і потім назавжди викинута в порожнечу . Це означає, що декларація функції або методу не залишається в пам'яті.
void
. Мені це подобається.
Спочатку ви повинні відвідати MDN IIFE , а тепер деякі моменти з цього приводу
Схоже, на це питання відповіли всі готові, але я все-таки опублікую свої дані.
Я знаю, коли мені подобається використовувати функції самовиконання.
var myObject = {
childObject: new function(){
// bunch of code
},
objVar1: <value>,
objVar2: <value>
}
Функція дозволяє мені використовувати деякий додатковий код для визначення атрибутів і властивостей childObjects для більш чистого коду, наприклад встановлення часто використовуваних змінних або виконання математичних рівнянь; Ой! або перевірка помилок. на відміну від обмеженості синтаксисом вкладеного об'єкта інстанції ...
object: {
childObject: {
childObject: {<value>, <value>, <value>}
},
objVar1: <value>,
objVar2: <value>
}
Кодування взагалі має багато незрозумілих способів робити багато одних і тих же речей, змушуючи замислюватися: "Чому турбуватись?" Але виникають нові ситуації, коли ви більше не можете покладатися на основні / основні принципи.
З огляду на ваше просте запитання: "У javascript, коли ви хочете використовувати це: ..."
Мені подобаються відповіді @ken_browning та @ sean_holding, але ось ще один випадок використання, який я не бачу згаданого:
let red_tree = new Node(10);
(async function () {
for (let i = 0; i < 1000; i++) {
await red_tree.insert(i);
}
})();
console.log('----->red_tree.printInOrder():', red_tree.printInOrder());
де Node.insert - деяка асинхронна дія.
Я не можу просто зателефонувати в очікуванні без ключового слова async при оголошенні моєї функції, і мені не потрібна названа функція для подальшого використання, але мені потрібно дочекатися цього вставлення виклику або мені потрібні інші більш багаті функції (хто знає?) .
IIRC дозволяє створювати приватні властивості та методи.