diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:15 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:15 -0500 |
commit | 4b1a9203c547c019fc5398082ae19a3f3d4c3efe (patch) | |
tree | d4a40e13ceeb9f85479605110a76e7a4d5f3b56b /files/bg/web/javascript/reference/functions | |
parent | 33058f2b292b3a581333bdfb21b8f671898c5060 (diff) | |
download | translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.tar.gz translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.tar.bz2 translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.zip |
initial commit
Diffstat (limited to 'files/bg/web/javascript/reference/functions')
-rw-r--r-- | files/bg/web/javascript/reference/functions/arrow_functions/index.html | 394 | ||||
-rw-r--r-- | files/bg/web/javascript/reference/functions/index.html | 596 |
2 files changed, 990 insertions, 0 deletions
diff --git a/files/bg/web/javascript/reference/functions/arrow_functions/index.html b/files/bg/web/javascript/reference/functions/arrow_functions/index.html new file mode 100644 index 0000000000..f2efe8ec10 --- /dev/null +++ b/files/bg/web/javascript/reference/functions/arrow_functions/index.html @@ -0,0 +1,394 @@ +--- +title: Arrow functions +slug: Web/JavaScript/Reference/Functions/Arrow_functions +tags: + - Средно напреднали + - Функции + - Функции със стрелка + - референция +translation_of: Web/JavaScript/Reference/Functions/Arrow_functions +--- +<div>{{jsSidebar("Functions")}}</div> + +<p>Функционалният израз със стрелка има по-кратък синтаксис, отколкото стандартното дефиниране на функция и няма свой собствен <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/super">super</a></code>, или <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a></code>. Тези функции не са подходящи за изполване като метод функции(methods) и не могат да бъдат използвани като конструктори.</p> + +<div>{{EmbedInteractiveExample("pages/js/functions-arrow.html")}}</div> + +<h2 id="Синтаксис">Синтаксис</h2> + +<h3 id="Основен_синтаксис">Основен синтаксис</h3> + +<pre class="syntaxbox notranslate">(param1, param2, …, paramN) => { statements } +(param1, param2, …, paramN) => expression +// равнозначно на: => { return expression; } + +// Скобите не са задължителни, когато има само един входен параметър: +(singleParam) => { statements } +singleParam => { statements } + +// Списъка с аргументи за функции без аргументи трябва да бъде написан, като се използват скоби. +() => { statements } +</pre> + +<h3 id="Напреднал_синтаксис">Напреднал синтаксис</h3> + +<pre class="syntaxbox notranslate">// Резултата може да бъде ограден в скоби за да бъде върнат под формата на обект(object literal expression): +params => ({foo: bar}) + +// Поддържат се <a href="/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters">Rest </a>оператора и <a href="en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters">параметри по подразбиране</a> +(param1, param2, ...rest) => { statements } +(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { +statements } + +// <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">Деструктуриране</a> на списъка с входни аргументи също се поддържа +var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; +f(); // 6 +</pre> + +<h2 id="Описание">Описание</h2> + +<p>Вижте също <a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a>.</p> + +<p>Два фактора повлияха за въвеждането на функциите със стрелка: по-къси функции и липсата на ключовата дума <code>this</code>.</p> + +<h3 id="По-кракти_функции">По-кракти функции</h3> + +<pre class="brush: js notranslate">var elements = [ + 'Hydrogen', + 'Helium', + 'Lithium', + 'Beryllium' +]; + +elements.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(function(element) { + return element.length; +}); // извикването на описания код ще върне следния масив: [8, 6, 7, 9] + +// Горе описаната функция може да бъде написана и като функция със стрелка по следния начин +elements.map((element) => { + return element.length; +}); // [8, 6, 7, 9] + +// Когато има само един входен параметър можем да премахнем скобите: +elements.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(element => { + return element.length; +}); // [8, 6, 7, 9] + +// Когато единственото нещо в функцията е връщане на резултат, можем да премахнем `return` +// и също така да премахнем скобите +elements.map(element => element.length); // [8, 6, 7, 9] + +// In this case, because we only need the length property, we can use destructing parameter: +// Notice that the string `"length"` corrosponds to the property we want to get whereas the +// obviously non-special `lengthFooBArX` is just the name of a variable which can be changed +// to any valid variable name you want +elements.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(({ "length": lengthFooBArX }) => lengthFooBArX); // [8, 6, 7, 9] + +// This destructing parameter assignment can be written as seen below. However, note that there +// is no specific `"length"` to select which property we want to get. Instead, the literal name +// itself of the variable `length` is used as the property we want to retrieve from the object. +elements.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(({ length }) => length); // [8, 6, 7, 9] +</pre> + +<h3 id="Без_отделна_ключова_дума_this">Без отделна ключова дума <code>this</code></h3> + +<p>Допреди функциите със стрелка, всяка нова функция дефинираше своя собствена стойност <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code> (въз основа на това как се нарича функцията, нов обект в случай на конструктор, недифинарна при извикване на функции в <a href="/en-US/docs/Web/JavaScript/Reference/Strict_mode">строг режим</a>,основният обект ако функцията се извиква като "object method", etc.). Това се оказа по-малко от идеалното с обектно-ориентирания стил на програмиране.</p> + +<pre class="brush: js notranslate">function Person() { + // The Person() constructor defines `this` as an instance of itself. + this.age = 0; + + setInterval(function growUp() { + // In non-strict mode, the growUp() function defines `this` + // as the global object (because it's where growUp() is executed.), + // which is different from the `this` + // defined by the Person() constructor. + this.age++; + }, 1000); +} + +var p = new Person();</pre> + +<p>В ECMAScript 3/5, проблемът с <code>this</code> беше поправим като присвоим стойността на <code>this</code> към променлива , която може да бъде затворена.</p> + +<pre class="brush: js notranslate">function Person() { + var that = this; + that.age = 0; + + setInterval(function growUp() { + // The callback refers to the `that` variable of which + // the value is the expected object. + that.age++; + }, 1000); +}</pre> + +<p>Като алтернатива, може да бъде създадена <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">свързана функция</a> така че <code>this</code> стойността може да бъде предадена на свързаната целева функция (функцията <code>growUp()</code> в примера по-горе).</p> + +<p>Функцията със стрелка няма свой собствен <code>this;</code> Стойността <code>this</code> от използвания лексикален контекст и др. <span style="background-color: #ffffff; color: #212121; display: inline !important; float: none; font-family: arial,sans-serif; font-size: 16px; font-style: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: pre-wrap;">Функциите със стрелки следват </span>нормалните правила на промелнива. Така че, докато търсим за <code>this,</code> който не присъства в текущият обхват на функцията, те взимат <code>this</code> от околният обхват. По този начин,в следния код, <code>this</code> <span lang="bg">в рамките на функцията</span>, която се предава на <code>setInterval</code> функцията, има същата стойност като на тази в околната лексикална функция:</p> + +<pre class="brush: js notranslate">function Person(){ + this.age = 0; + + setInterval(() => { + this.age++; // |this| properly refers to the Person object + }, 1000); +} + +var p = new Person();</pre> + +<h4 id="Връзка_със_строг_режим">Връзка със строг режим</h4> + +<p>Като се има в предвид , че <code>this</code> идва от околния лексикален контекст, <a href="/en-US/docs/Web/JavaScript/Reference/Strict_mode">строгите правила за режима</a> по отношение на <code>this</code> се игнорират.</p> + +<pre class="brush: js notranslate">var f = () => { 'use strict'; return this; }; +f() === window; // or the global object</pre> + +<p><span lang="bg">Всички други правила за строг режим се прилагат нормално</span></p> + +<h4 id="Извикване_чрез_повикване_или_прилагане">Извикване чрез повикване или прилагане</h4> + +<p>Тъй като функциите със стрелка нямат свой собствен <code>this</code>, методите <code>call()</code> <code>или apply()</code> могат само да предават параметри. <code>thisArg</code> се игнорира.</p> + +<pre class="brush: js notranslate">var adder = { + base: 1, + + add: function(a) { + var f = v => v + this.base; + return f(a); + }, + + addThruCall: function(a) { + var f = v => v + this.base; + var b = { + base: 2 + }; + + return f.call(b, a); + } +}; + +console.log(adder.add(1)); // This would log to 2 +console.log(adder.addThruCall(1)); // This would log to 2 still</pre> + +<h3 id="Без_обвързване_на_arguments">Без обвързване на <code>arguments</code></h3> + +<p>Функциите със стрелка нямат свой собствен <a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments">обект</a> от <a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments"><code>аргументи</code> </a>.<span style="background-color: #ffffff; color: #212121; display: inline !important; float: none; font-family: arial,sans-serif; font-size: 16px; font-style: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: pre-wrap;">Следователно в този пример <code>аргументите </code>са просто препратка към аргументите на заобикалящото ги поле</span>:</p> + +<pre class="brush: js notranslate">var arguments = [1, 2, 3]; +var arr = () => arguments[0]; + +arr(); // 1 + +function foo(n) { + var f = () => arguments[0] + n; // <em>foo</em>'s implicit arguments binding. arguments[0] is n + return f(); +} + +foo(3); // 6</pre> + +<p>В повечето случаи, използването на <a href="/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters">rest parameters(остатъчни параметри)</a> е добра алтернатива от използването на обект с <code>аргументи</code>.</p> + +<pre class="brush: js notranslate">function foo(n) { + var f = (...args) => args[0] + n; + return f(10); +} + +foo(1); // 11</pre> + +<h3 id="Функции_със_стрелка_използвани_като_методи">Функции със стрелка използвани като методи</h3> + +<p><span class="tlid-translation translation"><span title="">Както бе посочено по-горе, изразите на функциите със стрелките са най-подходящи за функциите, различни от метода.</span> <span title="">Нека видим какво се случва, когато се опитаме да ги използваме като методи:</span></span></p> + +<pre class="brush: js notranslate">'use strict'; + +var obj = { + i: 10, + b: () => console.log(this.i, this), + c: function() { + console.log(this.i, this); + } +} + +obj.b(); // prints undefined, Window {...} (or the global object) +obj.c(); // prints 10, Object {...}</pre> + +<p>Функциите със стрелка нямат свой собствен <code>this</code>. Друг пример затова е : {{jsxref("Object.defineProperty()")}}:</p> + +<pre class="brush: js notranslate">'use strict'; + +var obj = { + a: 10 +}; + +Object.defineProperty(obj, 'b', { + get: () => { + console.log(this.a, typeof this.a, this); // undefined 'undefined' Window {...} (or the global object) + return this.a + 10; // represents global object 'Window', therefore 'this.a' returns 'undefined' + } +}); +</pre> + +<h3 id="Използване_на_оператора_new">Използване на оператора <code>new</code></h3> + +<p>Функциите със стрелка не мога да бъдат използвани като конструктории ще генерират грешка , когато се изпозват с оператора <code>new</code>.</p> + +<pre class="brush: js notranslate">var Foo = () => {}; +var foo = new Foo(); // TypeError: Foo is not a constructor</pre> + +<h3 id="Използване_на_свойството_prototype">Използване на свойството <code>prototype</code></h3> + +<p>Функциите със стрелки нямат свойството <code>prototype</code>.</p> + +<pre class="brush: js notranslate">var Foo = () => {}; +console.log(Foo.prototype); // undefined +</pre> + +<h3 id="Използване_на_ключовата_дума_yield">Използване на ключовата дума <code>yield</code></h3> + +<p><span class="tlid-translation translation"><span title="">Ключовата дума</span></span> <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/yield">yield</a></code> не може да бъде използвана в тялото на функцията със стрелка ( <span class="tlid-translation translation"><span title="">освен когато е позволено в рамките на функциите, които са вложени в нея</span></span> ). <span class="tlid-translation translation"><span title="">В резултат на това функциите със стрелки не могат да се използват като генератори.</span></span></p> + +<h2 id="Тялото_на_функция">Тялото на функция</h2> + +<p>Функциите със стрелка могат да имат или "сбито тяло" или обичайното "блоково тяло".</p> + +<p>В сбитото тяло е посочен само израз, който се превръща в неявна връщана стойност. <span class="tlid-translation translation"><span title="">В блоково тяло трябва да използвате изрично <code>return</code> декларация за връщане.</span></span></p> + +<pre class="brush: js notranslate">var func = x => x * x; +// concise body syntax, implied "return" + +var func = (x, y) => { return x + y; }; +// with block body, explicit "return" needed +</pre> + +<h2 id="Връщане_на_литерали_на_обекти">Връщане на литерали на обекти</h2> + +<p>Имайте в предвид , че връщането на литерали на обекти, използвайки сбит синтаксис <code>params => {object:literal}</code> няма да работи според очакванията.</p> + +<pre class="brush: js notranslate">var func = () => { foo: 1 }; +// Calling func() returns undefined! + +var func = () => { foo: function() {} }; +// SyntaxError: function statement requires a name</pre> + +<p>Това е защото кодът вътре в скобите ({}) се анализита като оследователност от изрази (или <code>foo</code>се третира като етикет, а не като ключ в буквален обект).</p> + +<p>Запомнете, че трябва да поставяте буквалният обект в скоби , както е показано в примера по-долу.</p> + +<pre class="brush: js notranslate">var func = () => ({foo: 1});</pre> + +<h2 id="Прекъсване_на_линията">Прекъсване на линията</h2> + +<p>Функцията със стрелка не може да съдържа прекъсната линия между нейните параметри и стрелка.</p> + +<pre class="brush: js notranslate">var func = (a, b, c) + => 1; +// SyntaxError: expected expression, got '=>'</pre> + +<p><span class="tlid-translation translation"><span title="">Все пак това може да бъде променено, чрез използване на скоби или поставяне на разделителната линия в аргументите, както е показано в примера по-долу, за да се гарантира, че кодът остава красив и пухкав.</span></span></p> + +<pre class="brush: js notranslate">var func = ( + a, + b, + c +) => ( + 1 +); +// no SyntaxError thrown</pre> + + + +<h2 id="Parsing_order">Parsing order</h2> + +<p>Въпреки че, стрелката във функцията със стрелка не е оператор, функциите със стрелка имат специални правила, които взаимодействат по различен начин с <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence">оператора за предимство </a> сравнено с нормалните функции.</p> + +<pre class="brush: js notranslate">let callback; + +callback = callback || function() {}; // ok + +callback = callback || () => {}; +// SyntaxError: invalid arrow-function arguments + +callback = callback || (() => {}); // ok +</pre> + +<h2 id="Още_примери">Още примери</h2> + +<pre class="brush: js notranslate">// An empty arrow function returns undefined +let empty = () => {}; + +(() => 'foobar')(); +// Returns "foobar" +// (this is an Immediately Invoked Function Expression +// see 'IIFE' in glossary) + +var simple = a => a > 15 ? 15 : a; +simple(16); // 15 +simple(10); // 10 + +let max = (a, b) => a > b ? a : b; + +// Easy array filtering, mapping, ... + +var arr = [5, 6, 13, 0, 1, 18, 23]; + +var sum = arr.reduce((a, b) => a + b); +// 66 + +var even = arr.filter(v => v % 2 == 0); +// [6, 0, 18] + +var double = arr.map(v => v * 2); +// [10, 12, 26, 0, 2, 36, 46] + +// More concise promise chains +promise.then(a => { + // ... +}).then(b => { + // ... +}); + +// Parameterless arrow functions that are visually easier to parse +setTimeout( () => { + console.log('I happen sooner'); + setTimeout( () => { + // deeper code + console.log('I happen later'); + }, 1); +}, 1); +</pre> + +<h2 id="Спецификации">Спецификации</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Спецификации</th> + <th scope="col">Статус</th> + <th scope="col">Коментар</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="Съвместимост_с_браузера">Съвместимост с браузера</h2> + +<div> + + +<p>{{Compat("javascript.functions.arrow_functions")}}</p> +</div> + +<h2 id="Вижте_още">Вижте още</h2> + +<ul> + <li><a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a></li> +</ul> diff --git a/files/bg/web/javascript/reference/functions/index.html b/files/bg/web/javascript/reference/functions/index.html new file mode 100644 index 0000000000..adb0d13f05 --- /dev/null +++ b/files/bg/web/javascript/reference/functions/index.html @@ -0,0 +1,596 @@ +--- +title: Functions +slug: Web/JavaScript/Reference/Functions +tags: + - Constructor + - Function + - Functions + - JavaScript + - NeedsTranslation + - Parameter + - TopicStub + - parameters +translation_of: Web/JavaScript/Reference/Functions +--- +<div>{{jsSidebar("Functions")}}</div> + +<p>Generally speaking, a function is a "subprogram" that can be <em>called</em> by code external (or internal in the case of recursion) to the function. Like the program itself, a function is composed of a sequence of statements called the <em>function body</em>. Values can be <em>passed</em> to a function, and the function will <em>return</em> a value.</p> + +<p>In JavaScript, functions are first-class objects, because they can have properties and methods just like any other object. What distinguishes them from other objects is that functions can be called. In brief, they are <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Function">Function</a></code> objects.</p> + +<p>For more examples and explanations, see also the <a href="/en-US/docs/Web/JavaScript/Guide/Functions">JavaScript guide about functions</a>.</p> + +<h2 id="Description">Description</h2> + +<p>Every function in JavaScript is a <code>Function</code> object. See {{jsxref("Function")}} for information on properties and methods of <code>Function</code> objects.</p> + +<p>To return a value other than the default, a function must have a <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/return">return</a></code> statement that specifies the value to return. A function without a return statement will return a default value. In the case of a <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">constructor</a> called with the <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/new">new</a></code> keyword, the default value is the value of its <code>this</code> parameter. For all other functions, the default return value is {{jsxref("undefined")}}.</p> + +<p>The parameters of a function call are the function's <em>arguments</em>. Arguments are passed to functions <em>by value</em>. If the function changes the value of an argument, this change is not reflected globally or in the calling function. However, object references are values, too, and they are special: if the function changes the referred object's properties, that change is visible outside the function, as shown in the following example:</p> + +<pre class="brush: js">/* Declare the function 'myFunc' */ +function myFunc(theObject) { + theObject.brand = "Toyota"; +} + +/* + * Declare variable 'mycar'; + * create and initialize a new Object; + * assign reference to it to 'mycar' + */ +var mycar = { + brand: "Honda", + model: "Accord", + year: 1998 +}; + +/* Logs 'Honda' */ +console.log(mycar.brand); + +/* Pass object reference to the function */ +myFunc(mycar); + +/* + * Logs 'Toyota' as the value of the 'brand' property + * of the object, as changed to by the function. + */ +console.log(mycar.brand); +</pre> + +<p>The <a href="/en-US/docs/Web/JavaScript/Reference/Operators/this"><code>this</code> keyword</a> does not refer to the currently executing function, so you must refer to <code>Function</code> objects by name, even within the function body.</p> + +<h2 id="Defining_functions">Defining functions</h2> + +<p>There are several ways to define functions:</p> + +<h3 id="The_function_declaration_(function_statement)">The function declaration (<code>function</code> statement)</h3> + +<p>There is a special syntax for declaring functions (see <a href="/en-US/docs/Web/JavaScript/Reference/Statements/function">function statement</a> for details):</p> + +<pre class="syntaxbox">function <em>name</em>([<em>param</em>[, <em>param</em>[, ... <em>param</em>]]]) { + <em>statements</em> +} +</pre> + +<dl> + <dt><code>name</code></dt> + <dd>The function name.</dd> +</dl> + +<dl> + <dt><code>param</code></dt> + <dd>The name of an argument to be passed to the function.</dd> +</dl> + +<dl> + <dt><code>statements</code></dt> + <dd>The statements comprising the body of the function.</dd> +</dl> + +<h3 id="The_function_expression_(function_expression)">The function expression (<code>function</code> expression)</h3> + +<p>A function expression is similar to and has the same syntax as a function declaration (see <a href="/en-US/docs/Web/JavaScript/Reference/Operators/function">function expression</a> for details). A function expression may be a part of a larger expression. One can define "named" function expressions (where the name of the expression might be used in the call stack for example) or "anonymous" function expressions. Function expressions are not <em>hoisted</em> onto the beginning of the scope, therefore they cannot be used before they appear in the code.</p> + +<pre class="syntaxbox">function [<em>name</em>]([<em>param</em>[, <em>param</em>[, ... <em>param</em>]]]) { + <em>statements</em> +} +</pre> + +<dl> + <dt><code>name</code></dt> + <dd>The function name. Can be omitted, in which case the function becomes known as an anonymous function.</dd> +</dl> + +<dl> + <dt><code>param</code></dt> + <dd>The name of an argument to be passed to the function.</dd> + <dt><code>statements</code></dt> + <dd>The statements comprising the body of the function.</dd> +</dl> + +<p>Here is an example of an <strong>anonymous</strong> function expression (the <code>name</code> is not used):</p> + +<pre class="brush: js">var myFunction = function() { + statements +}</pre> + +<p>It is also possible to provide a name inside the definition in order to create a <strong>named</strong> function expression:</p> + +<pre class="brush: js">var myFunction = function namedFunction(){ + statements +} +</pre> + +<p>One of the benefits of creating a named function expression is that in case we encountered an error, the stack trace will contain the name of the function, making it easier to find the origin of the error.</p> + +<p>As we can see, both examples do not start with the <code>function</code> keyword. Statements involving functions which do not start with <code>function</code> are function expressions.</p> + +<p>When functions are used only once, a common pattern is an <a href="/en-US/docs/Glossary/IIFE">IIFE (Immediately Invokable Function Expression)</a>.</p> + +<pre class="brush: js">(function() { + statements +})();</pre> + +<p>IIFE are function expressions that are invoked as soon as the function is declared.</p> + +<h3 id="The_generator_function_declaration_(function*_statement)">The generator function declaration (<code>function*</code> statement)</h3> + +<p>There is a special syntax for generator function declarations (see {{jsxref('Statements/function*', 'function* statement')}} for details):</p> + +<pre class="syntaxbox">function* <em>name</em>([<em>param</em>[, <em>param</em>[, ... <em>param</em>]]]) { + <em>statements</em> +} +</pre> + +<dl> + <dt><code>name</code></dt> + <dd>The function name.</dd> +</dl> + +<dl> + <dt><code>param</code></dt> + <dd>The name of an argument to be passed to the function.</dd> +</dl> + +<dl> + <dt><code>statements</code></dt> + <dd>The statements comprising the body of the function.</dd> +</dl> + +<h3 id="The_generator_function_expression_(function*_expression)">The generator function expression (<code>function*</code> expression)</h3> + +<p>A generator function expression is similar to and has the same syntax as a generator function declaration (see {{jsxref('Operators/function*', 'function* expression')}} for details):</p> + +<pre class="syntaxbox">function* [<em>name</em>]([<em>param</em>[, <em>param</em>[, ... <em>param</em>]]]) { + <em>statements</em> +} +</pre> + +<dl> + <dt><code>name</code></dt> + <dd>The function name. Can be omitted, in which case the function becomes known as an anonymous function.</dd> +</dl> + +<dl> + <dt><code>param</code></dt> + <dd>The name of an argument to be passed to the function.</dd> + <dt><code>statements</code></dt> + <dd>The statements comprising the body of the function.</dd> +</dl> + +<h3 id="The_arrow_function_expression_(>)">The arrow function expression (=>)</h3> + +<p>An arrow function expression has a shorter syntax and lexically binds its <code>this</code> value (see <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">arrow functions</a> for details):</p> + +<pre class="syntaxbox">([param[, param]]) => { + statements +} + +param => expression +</pre> + +<dl> + <dt><code>param</code></dt> + <dd>The name of an argument. Zero arguments need to be indicated with <code>()</code>. For only one argument, the parentheses are not required. (like <code>foo => 1</code>)</dd> + <dt><code>statements or expression</code></dt> + <dd>Multiple statements need to be enclosed in brackets. A single expression requires no brackets. The expression is also the implicit return value of the function.</dd> +</dl> + +<h3 id="The_Function_constructor">The <code>Function</code> constructor</h3> + +<div class="note"> +<p><strong>Note:</strong> Using the <code>Function</code> constructor to create functions is not recommended since it needs the function body as a string which may prevent some JS engine optimizations and can also cause other problems.</p> +</div> + +<p>As all other objects, {{jsxref("Function")}} objects can be created using the <code>new</code> operator:</p> + +<pre class="syntaxbox">new Function (<em>arg1</em>, <em>arg2</em>, ... <em>argN</em>, <em>functionBody</em>) +</pre> + +<dl> + <dt><code>arg1, arg2, ... arg<em>N</em></code></dt> + <dd>Zero or more names to be used by the function as formal parameters. Each must be a proper JavaScript identifier.</dd> +</dl> + +<dl> + <dt><code>functionBody</code></dt> + <dd>A string containing the JavaScript statements comprising the function body.</dd> +</dl> + +<p>Invoking the <code>Function</code> constructor as a function (without using the <code>new</code> operator) has the same effect as invoking it as a constructor.</p> + +<h3 id="The_GeneratorFunction_constructor">The <code>GeneratorFunction</code> constructor</h3> + +<div class="note"> +<p><strong>Note:</strong> <code>GeneratorFunction</code> is not a global object, but could be obtained from generator function instance (see {{jsxref("GeneratorFunction")}} for more detail).</p> +</div> + +<div class="note"> +<p><strong>Note:</strong> Using the <code>GeneratorFunction</code> constructor to create functions is not recommended since it needs the function body as a string which may prevent some JS engine optimizations and can also cause other problems.</p> +</div> + +<p>As all other objects, {{jsxref("GeneratorFunction")}} objects can be created using the <code>new</code> operator:</p> + +<pre class="syntaxbox">new GeneratorFunction (<em>arg1</em>, <em>arg2</em>, ... <em>argN</em>, <em>functionBody</em>) +</pre> + +<dl> + <dt><code>arg1, arg2, ... arg<em>N</em></code></dt> + <dd>Zero or more names to be used by the function as formal argument names. Each must be a string that conforms to the rules for a valid JavaScript identifier or a list of such strings separated with a comma; for example "<code>x</code>", "<code>theValue</code>", or "<code>a,b</code>".</dd> +</dl> + +<dl> + <dt><code>functionBody</code></dt> + <dd>A string containing the JavaScript statements comprising the function definition.</dd> +</dl> + +<p>Invoking the <code>Function</code> constructor as a function (without using the <code>new</code> operator) has the same effect as invoking it as a constructor.</p> + +<h2 id="Function_parameters">Function parameters</h2> + +<h3 id="Default_parameters">Default parameters</h3> + +<p>Default function parameters allow formal parameters to be initialized with default values if no value or <code>undefined</code> is passed. For more details, see<a href="/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters"> default parameters</a>.</p> + +<h3 id="Rest_parameters">Rest parameters</h3> + +<p>The rest parameter syntax allows representing an indefinite number of arguments as an array. For more details, see <a href="/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters">rest parameters</a>.</p> + +<h2 id="The_arguments_object">The <code>arguments</code> object</h2> + +<p>You can refer to a function's arguments within the function by using the <code>arguments</code> object. See <a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a>.</p> + +<ul> + <li><code><a href="/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments">arguments</a></code>: An array-like object containing the arguments passed to the currently executing function.</li> + <li><code><a href="/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee">arguments.callee</a></code> {{Deprecated_inline}}: The currently executing function.</li> + <li><code><a href="/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/caller">arguments.caller</a></code> {{Obsolete_inline}} : The function that invoked the currently executing function.</li> + <li><code><a href="/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/length">arguments.length</a></code>: The number of arguments passed to the function.</li> +</ul> + +<h2 id="Defining_method_functions">Defining method functions</h2> + +<h3 id="Getter_and_setter_functions">Getter and setter functions</h3> + +<p>You can define getters (accessor methods) and setters (mutator methods) on any standard built-in object or user-defined object that supports the addition of new properties. The syntax for defining getters and setters uses the object literal syntax.</p> + +<dl> + <dt><a href="/en-US/docs/Web/JavaScript/Reference/Functions/get">get</a></dt> + <dd> + <p>Binds an object property to a function that will be called when that property is looked up.</p> + </dd> + <dt><a href="/en-US/docs/Web/JavaScript/Reference/Functions/set">set</a></dt> + <dd>Binds an object property to a function to be called when there is an attempt to set that property.</dd> +</dl> + +<h3 id="Method_definition_syntax">Method definition syntax</h3> + +<p>Starting with ECMAScript 2015, you are able to define own methods in a shorter syntax, similar to the getters and setters. See <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions">method definitions</a> for more information.</p> + +<pre class="brush: js">var obj = { + foo() {}, + bar() {} +};</pre> + +<h2 id="Constructor_vs._declaration_vs._expression">Constructor vs. declaration vs. expression</h2> + +<p>Compare the following:</p> + +<p>A function defined with the <code>Function</code> <em>constructor</em> assigned to the variable <code>multiply:</code></p> + +<pre class="brush: js">var multiply = new Function('x', 'y', 'return x * y');</pre> + +<p>A <em>function declaration</em> of a function named <code>multiply</code>:</p> + +<pre class="brush: js">function multiply(x, y) { + return x * y; +} // there is no semicolon here +</pre> + +<p>A <em>function expression</em> of an anonymous function assigned to the variable <code>multiply:</code></p> + +<pre class="brush: js">var multiply = function(x, y) { + return x * y; +}; +</pre> + +<p>A <em>function expression</em> of a function named <code>func_name</code> assigned to the variable <code>multiply:</code></p> + +<pre class="brush: js">var multiply = function func_name(x, y) { + return x * y; +}; +</pre> + +<h3 id="Differences">Differences</h3> + +<p>All do approximately the same thing, with a few subtle differences:</p> + +<p>There is a distinction between the function name and the variable the function is assigned to. The function name cannot be changed, while the variable the function is assigned to can be reassigned. The function name can be used only within the function's body. Attempting to use it outside the function's body results in an error (or <code>undefined</code> if the function name was previously declared via a <code>var</code> statement). For example:</p> + +<pre class="brush: js">var y = function x() {}; +alert(x); // throws an error +</pre> + +<p>The function name also appears when the function is serialized via <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString"><code>Function</code>'s toString method</a>.</p> + +<p>On the other hand, the variable the function is assigned to is limited only by its scope, which is guaranteed to include the scope in which the function is declared.</p> + +<p>As the 4th example shows, the function name can be different from the variable the function is assigned to. They have no relation to each other. A function declaration also creates a variable with the same name as the function name. Thus, unlike those defined by function expressions, functions defined by function declarations can be accessed by their name in the scope they were defined in:</p> + +<p>A function defined by '<code>new Function'</code> does not have a function name. However, in the <a href="/en-US/docs/Mozilla/Projects/SpiderMonkey">SpiderMonkey</a> JavaScript engine, the serialized form of the function shows as if it has the name "anonymous". For example, <code>alert(new Function())</code> outputs:</p> + +<pre class="brush: js">function anonymous() { +} +</pre> + +<p>Since the function actually does not have a name, <code>anonymous</code> is not a variable that can be accessed within the function. For example, the following would result in an error:</p> + +<pre class="brush: js">var foo = new Function("alert(anonymous);"); +foo(); +</pre> + +<p>Unlike functions defined by function expressions or by the <code>Function</code> constructor, a function defined by a function declaration can be used before the function declaration itself. For example:</p> + +<pre class="brush: js">foo(); // alerts FOO! +function foo() { + alert('FOO!'); +} +</pre> + +<p>A function defined by a function expression or by a function declaration inherits the current scope. That is, the function forms a closure. On the other hand, a function defined by a <code>Function</code> constructor does not inherit any scope other than the global scope (which all functions inherit).</p> + +<pre class="brush: js">/* + * Declare and initialize a variable 'p' (global) + * and a function 'myFunc' (to change the scope) inside which + * declare a varible with same name 'p' (current) and + * define three functions using three different ways:- + * 1. function declaration + * 2. function expression + * 3. function constructor + * each of which will log 'p' + */ +var p = 5; +function myFunc() { + var p = 9; + + function decl() { + console.log(p); + } + var expr = function() { + console.log(p); + }; + var cons = new Function('\tconsole.log(p);'); + + decl(); + expr(); + cons(); +} +myFunc(); + +/* + * Logs:- + * 9 - for 'decl' by function declaration (current scope) + * 9 - for 'expr' by function expression (current scope) + * 5 - for 'cons' by Function constructor (global scope) + */ +</pre> + +<p>Functions defined by function expressions and function declarations are parsed only once, while those defined by the <code>Function</code> constructor are not. That is, the function body string passed to the <code>Function</code> constructor must be parsed each and every time the constructor is called. Although a function expression creates a closure every time, the function body is not reparsed, so function expressions are still faster than "<code>new Function(...)</code>". Therefore the <code>Function</code> constructor should generally be avoided whenever possible.</p> + +<p>It should be noted, however, that function expressions and function declarations nested within the function generated by parsing a <code>Function constructor</code> 's string aren't parsed repeatedly. For example:</p> + +<pre class="brush: js">var foo = (new Function("var bar = \'FOO!\';\nreturn(function() {\n\talert(bar);\n});"))(); +foo(); // The segment "function() {\n\talert(bar);\n}" of the function body string is not re-parsed.</pre> + +<p>A function declaration is very easily (and often unintentionally) turned into a function expression. A function declaration ceases to be one when it either:</p> + +<ul> + <li>becomes part of an expression</li> + <li>is no longer a "source element" of a function or the script itself. A "source element" is a non-nested statement in the script or a function body:</li> +</ul> + +<pre class="brush: js">var x = 0; // source element +if (x === 0) { // source element + x = 10; // not a source element + function boo() {} // not a source element +} +function foo() { // source element + var y = 20; // source element + function bar() {} // source element + while (y === 10) { // source element + function blah() {} // not a source element + y++; // not a source element + } +} +</pre> + +<h3 id="Examples">Examples</h3> + +<pre class="brush: js">// function declaration +function foo() {} + +// function expression +(function bar() {}) + +// function expression +x = function hello() {} + + +if (x) { + // function expression + function world() {} +} + + +// function declaration +function a() { + // function declaration + function b() {} + if (0) { + // function expression + function c() {} + } +} +</pre> + +<h2 id="Block-level_functions">Block-level functions</h2> + +<p>In <a href="/en-US/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a>, starting with ES2015, functions inside blocks are now scoped to that block. Prior to ES2015, block-level functions were forbidden in strict mode.</p> + +<pre class="brush: js">'use strict'; + +function f() { + return 1; +} + +{ + function f() { + return 2; + } +} + +f() === 1; // true + +// f() === 2 in non-strict mode +</pre> + +<h3 id="Block-level_functions_in_non-strict_code">Block-level functions in non-strict code</h3> + +<p>In a word: Don't.</p> + +<p>In non-strict code, function declarations inside blocks behave strangely. For example:</p> + +<pre class="brush: js">if (shouldDefineZero) { + function zero() { // DANGER: compatibility risk + console.log("This is zero."); + } +} +</pre> + +<p>ES2015 says that if <code>shouldDefineZero</code> is false, then <code>zero</code> should never be defined, since the block never executes. However, it's a new part of the standard. Historically, this was left unspecified, and some browsers would define <code>zero</code> whether the block executed or not.</p> + +<p>In <a href="/en-US/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a>, all browsers that support ES2015 handle this the same way: <code>zero</code> is defined only if <code>shouldDefineZero</code> is true, and only in the scope of the <code>if</code>-block.</p> + +<p>A safer way to define functions conditionally is to assign a function expression to a variable:</p> + +<pre class="brush: js">var zero; +if (shouldDefineZero) { + zero = function() { + console.log("This is zero."); + }; +} +</pre> + +<h2 id="Examples_2">Examples</h2> + +<h3 id="Returning_a_formatted_number">Returning a formatted number</h3> + +<p>The following function returns a string containing the formatted representation of a number padded with leading zeros.</p> + +<pre class="brush: js">// This function returns a string padded with leading zeros +function padZeros(num, totalLen) { + var numStr = num.toString(); // Initialize return value as string + var numZeros = totalLen - numStr.length; // Calculate no. of zeros + for (var i = 1; i <= numZeros; i++) { + numStr = "0" + numStr; + } + return numStr; +} +</pre> + +<p>The following statements call the padZeros function.</p> + +<pre class="brush: js">var result; +result = padZeros(42,4); // returns "0042" +result = padZeros(42,2); // returns "42" +result = padZeros(5,4); // returns "0005" +</pre> + +<h3 id="Determining_whether_a_function_exists">Determining whether a function exists</h3> + +<p>You can determine whether a function exists by using the <code>typeof</code> operator. In the following example, a test is performed to determine if the <code>window</code> object has a property called <code>noFunc</code> that is a function. If so, it is used; otherwise, some other action is taken.</p> + +<pre class="brush: js"> if ('function' === typeof window.noFunc) { + // use noFunc() + } else { + // do something else + } +</pre> + +<p>Note that in the <code>if</code> test, a reference to <code>noFunc</code> is used—there are no brackets "()" after the function name so the actual function is not called.</p> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.0</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-13', 'Function Definition')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-function-definitions', 'Function definitions')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>New: Arrow functions, Generator functions, default parameters, rest parameters.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-function-definitions', 'Function definitions')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + + + +<p>{{Compat("javascript.functions")}}</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{jsxref("Statements/function", "function statement")}}</li> + <li>{{jsxref("Operators/function", "function expression")}}</li> + <li>{{jsxref("Statements/function*", "function* statement")}}</li> + <li>{{jsxref("Operators/function*", "function* expression")}}</li> + <li>{{jsxref("Function")}}</li> + <li>{{jsxref("GeneratorFunction")}}</li> + <li>{{jsxref("Functions/Arrow_functions", "Arrow functions")}}</li> + <li>{{jsxref("Functions/Default_parameters", "Default parameters")}}</li> + <li>{{jsxref("Functions/rest_parameters", "Rest parameters")}}</li> + <li>{{jsxref("Functions/arguments", "Arguments object")}}</li> + <li>{{jsxref("Functions/get", "getter")}}</li> + <li>{{jsxref("Functions/set", "setter")}}</li> + <li>{{jsxref("Functions/Method_definitions", "Method definitions")}}</li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope">Functions and function scope</a></li> +</ul> |