GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing en.wikibooks.org — JavaScript/Functions - Wikibooks, open books for an open world (Redirected from JavaScript/Anonymous functions)
A function is a block of code that solves a dedicated problem and returns the solution to the calling statement. The function exists in its own context. Hence, functions divide massive programs into smaller 'bricks' which structure the software as well as the software development process. // define a function function <function_name> (<parameters>) { <function_body> } // call a function <variable> = <function_name> (<arguments>); JavaScript supports the software development paradigm functional programming. Functions are a data type derived from Object; they can be bound to variables, passed as arguments, and returned from other functions, just as any other data type. DeclarationFunctions can be constructed in three main ways. The first version can be abbreviated further; see below. The conventional way: "use strict"; // conventional declaration (or 'definition') function duplication(p) { return p + "! " + p + "!"; } // call the function const ret = duplication("Go"); alert(ret); Construction via a variable and an expression: "use strict"; // assign the function to a variable let duplication = function (p) { return p + "! " + p + "!"; }; const ret = duplication("Go"); alert(ret); Construction via the "use strict"; // using the 'new' constructor let duplication = new Function ("p", "return p + '! ' + p + '!'"); const ret = duplication("Go"); alert(ret); InvocationFor the declaration of functions, we have seen 3 variants. For their invocation, there are also 3 variants. The declarations and invocations are independent of each other and you can arbitrarily combine them. The conventional invocation variant uses the function name followed by parenthesis "use strict"; function duplication(p) { return p + "! " + p + "!"; } // the conventional invocation method const ret = duplication("Go"); alert(ret); If the script runs in a browser, there are two more possibilities. They use the "use strict"; function duplication(p) { return p + "! " + p + "!"; } // via 'call' let ret = duplication.call(window, "Go"); alert(ret); // via 'apply' ret = duplication.apply(window, ["Go"]); alert(ret); Hint: If you use the function name without the parenthesis "use strict"; function duplication(p) { return p + "! " + p + "!"; } alert(duplication); // 'function duplication (p) { ... }' HoistingFunctions are subject to 'hoisting'. This mechanism transfers the declaration of a function automatically to the top of its scope. As a consequence, you can call a function from an upper place in the source code than its declaration. "use strict"; // use a function above (in source code) its declaration const ret = duplication("Go"); alert(ret); function duplication(p) { return p + "! " + p + "!"; } Immediately Invoked FunctionSo far, we have seen the two separate steps declaration and invocation. There is also a syntax variant that allows the combination of both. It is characterized by using parenthesis around the function declaration followed by "use strict"; alert( // 'alert' to show the result // declaration plus invocation (function (p) { return p + "! " + p + "!"; })("Go") // ("Go"): invocation with the argument "Go" ); alert( // the same with 'arrow' syntax ((p) => { return p + "! " + p + "!"; })("Gooo") ); This syntax is known as a Immediately Invoked Function Expression (IIEF). ArgumentsWhen functions are called, the parameters from the declaration phase are replaced by the arguments of the call. In the above declarations, we used the variable name Call-by-valueSuch substitutions are done 'by value' and not 'by reference'. A copy of the argument's original value is passed to the function. If this copied value is changed within the function, the original value outside of the function is not changed. "use strict"; // there is one parameter 'p' function duplication(p) { // In this example, we change the parameter's value p = "NoGo"; alert("In function: " + p); return p + "! " + p + "!"; }; let x = "Go"; const ret = duplication(x); // is the modification of the argument done in the function visible here? No. alert("Return value: " + ret + " Variable: " + x); For objects (all non-primitive data types), this 'call-by-value' has a - possibly - astonishing effect. If the function modifies a property of the object, this change is also seen outside. "use strict"; function duplication(p) { p.a = 2; // change the property's value p.b = 'xyz'; // add a property alert("In function: " + JSON.stringify(p)); return JSON.stringify(p) + "! " + JSON.stringify(p) + "!"; }; let x = {a: 1}; alert("Object: " + JSON.stringify(x)); const ret = duplication(x); // is the modification of the argument done in the function visible here? Yes. alert("Return value: " + ret + " Object: " + JSON.stringify(x)); When the example runs, it shows that after the invocation of The function receives a copy of the reference to the object. Hence, within the function, the same object is referenced. The object itself exists only one time, but there are two (identical) references to the object. It does not make a difference whether the object's properties are modified by one reference or the other. Another consequence is - and this may be intuitively the same as with primitive data types (?) - that the modification of the reference itself, e.g., by the creation of a new object, will not be visible in the outer routine. The reference to the new object is stored in the copy of the original reference. Now we have not only two references (with different values) but also two objects. "use strict"; function duplication(p) { // modify the reference by creating a new object p = {}; p.a = 2; // change the property's value p.b = 'xyz'; // add a property alert("In function: " + JSON.stringify(p)); return JSON.stringify(p) + "! " + JSON.stringify(p) + "!"; }; let x = {a: 1}; alert("Object: " + JSON.stringify(x)); const ret = duplication(x); // is the modification of the argument done in the function visible here? No. alert("Return value: " + ret + " Object: " + JSON.stringify(x)); Note 1: The naming of this argument-passing technique is not used consistently across different languages. Sometimes it is called 'call-by-sharing'. Wikipedia gives an overview. Note 2: The described consequences of JavaScript's argument-passing are comparable with the consequences of using the keyword Default valuesIf a function is invoked with fewer arguments than it contains parameters, the surplus parameters keep undefined. But you can define default values for this case by assigning a value within the function's signature. The missing parameters will get those as their default values. "use strict"; // two nearly identical functions; only the signature is slightly different function f1(a, b) { alert("The second parameter is: " + b) }; function f2(a, b = 10) { alert("The second parameter is: " + b) }; // identical invocations; different results f1(5); // undefined f1(5, 100); // 100 f2(5); // 10 f2(5, 100); // 100 Variable number of argumentsFor some functions, it is 'normal' that they get involved with different numbers of arguments. For example, think of a function that shows names. Individual checksThe 'normal' parameters, as well as the additional parameters, can be checked to determine whether they contain a value or not. "use strict"; function showName(firstName, familyName, academicTitle, titleOfNobility) { "use strict"; // handle required parameters let ret = ""; if (!firstName || !familyName) { return "first name and family name must be specified"; } ret = firstName + ", " + familyName; // handle optional parameters if (academicTitle) { ret = ret + ", " + academicTitle; } if (titleOfNobility) { ret = ret + ", " + titleOfNobility; } return ret; } alert(showName("Mike", "Spencer", "Ph.D.")); alert(showName("Tom")); Every single parameter that may not be given must be individually checked. The 'rest' parameterIf the handling of the optional parameters is structurally identical, the code can be simplified by using the rest operator syntax - mostly in combination with a loop. The syntax of the feature consists of three dots in the function's signature - like in the spread syntax. How does it work? As part of the function invocation, the JavaScript engine combines the given optional arguments into a single array. (Please note that the calling script does not use an array.) This array is given to the function as the last parameter. "use strict"; // the three dots (...) introduces the 'rest syntax' function showName(firstName, familyName, ...titles) { // handle required parameters let ret = ""; if (!firstName || !familyName) { return "first name and family name must be specified"; } ret = firstName + ", " + familyName; // handle optional parameters for (const title of titles) { ret = ret + ", " + title; } return ret; } alert(showName("Mike", "Spencer", "Ph.D.", "Duke")); alert(showName("Tom")); The third and all following arguments of the call are collected into a single array that is available in the function as the last parameter. This allows the use of a loop and simplifies the function's source code. The 'arguments' keywordIn accordance with other members of the C-family of programming languages, JavaScript offers the keyword Its functionality is comparable with the above rest syntax. The main difference is that "use strict"; function showName(firstName, familyName, academicTitles, titlesOfNobility) { // handle ALL parameters with a single keyword for (const arg of arguments) { alert(arg); } } showName("Mike", "Spencer", "Ph.D.", "Duke"); ReturnThe purpose of a function is to provide a solution of a dedicated problem. This solution is given back to the calling program by the Its syntax is A function runs until it reaches such a If there is no "use strict"; function duplication(p) { if (typeof p === 'object') { return; // return value: 'undefined' } else if (typeof p === 'string') { return p + "! " + p + "!"; } // implicit return with 'undefined' } let arg = ["Go", 4, {a: 1}]; for (let i = 0; i < arg.length; i++) { const ret = duplication(arg[i]); alert(ret); } Arrow functions (=>)Arrow functions are a compact alternative to the above-shown conventional function syntax. They abbreviate some language elements, omit others, and have only a few semantic distinctions in comparison to the original syntax. They are always anonymous but can be assigned to a variable. "use strict"; // original conventional syntax function duplication(p) { return p + "! " + p + "!"; } // 1. remove keyword 'function' and function name // 2. introduce '=>' instead // 3. remove 'return'; the last value is automatically returned (p) => { p + "! " + p + "!" } // remove { }, if only one statement (p) => p + "! " + p + "!" // Remove parameter parentheses if it is only one parameter // ----------------------------- p => p + "! " + p + "!" // that's all! // ----------------------------- alert( (p => p + "! " + p + "!")("Go") ); Here is one more example using an array. The "use strict"; const myArray = ['a', 'b', 'c']; myArray.forEach(e => alert("The element of the array is: " + e)); Other programming languages offer the concept of arrow functions under terms like anonymous functions or lambda expressions. Recursive InvocationsFunctions can call other functions. In real applications, this is often the case. A particular situation occurs when they call themselves. This is called a recursive invocation. Of course, this implies the danger of infinite loops. You must change something in the arguments to avoid this hurdle. Typically the need for such recursive calls arises when an application handles tree structures like bill of materials, a DOM tree, or genealogy information. Here we present the simple to implement mathematical problem of factorial computation. The factorial is the product of all positive integers less than or equal to a certain number , written as . For example, . It can be solved by a loop from to , but there is also a recursive solution. The factorial of is the already computed factorial of multiplied with , or in formulas: . This thought leads to the correspondent recursive construction of the function: "use strict"; function factorial(n) { if (n > 0) { const ret = n * factorial(n-1); return ret; } else { // n = 0; 0! is 1 return 1; } } const n = 4; alert(factorial(n)); As long as is greater than , the script calls ExercisesSee also |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |