Функция javascript возвращающая наибольшее значение. Пять способов вызвать функцию

Как создать функцию в JavaScript ? Такой вопрос достаточно распространён среди начинающих программистов. И эта статья написана как раз для таких новичков. Для начала необходимо разобраться с вопросом: а что такое функция? Давайте с этого и начнём.

Вы должны помнить из школы, что такое функция. Если нет, то напоминаю. У функции есть определённые параметры, которыми она манипулирует, и возвращает результат. Например, функция y = 2 * x +5. Здесь мы можем задать x = 3, а в ответ получим y = 11. Вот это пример функции из математики. Абсолютно аналогичные функции и в JavaScript , только тут функцией может быть не просто какое-то вычисление какого-то выражения, а всё, что угодно.

Давайте для начала создадим функцию, которая 3 раза выводит сообщение "Привет ".


function hello() {
alert("Привет");
alert("Привет");
alert("Привет");
}
hello();

Первая строчка сообщает, что дальше идёт сценарий на языке JavaScript . На следующей строке объявляется функция. Как видите, всё начинается с ключевого слова function . Внутри скобок указываются параметры, но в данном случае параметров нет, поэтому внутри скобок всё пусто. Дальше идут фигурные скобки, внутри которых находится код функции, который должен быть выполнен при её вызове. В качестве этого кода используется функция alert() , которая вызывает информационное окошко, в котором написан текст, заданный параметром. В качестве параметра мы функции alert() (это пример встроенной функции) передаём строку "Привет ". Функцию alert() мы вызываем три раза.

Когда функция написана, то необходимо поставить закрывающую фигурную скобку. На следующей строке мы вызываем функцию hello() . Надеюсь, Вам стало понятно, что такое функция. Возможно, что некоторые из Вас спросят: "А какие преимущества? Ведь мы могли бы просто написать три раза alert() и результат был бы тот же". Вы правы, и так и нужно поступать, если Вам нужно использовать этот код всего один раз. А представьте, что Вам это нужно 3, 4 или большее число раз. Разумеется, неудобно писать постоянно этот повторяющийся код. Гораздо проще написать одно слово hello(). Согласны? Думаю, что да. В конце статьи я, исходя из этого, сделаю один очень важный вывод, поэтому дочитайте её до конца.

Теперь поговорим о функциях с параметрами. Давайте создадим один из таких примеров (буду писать сразу функцию и её вызов, без тега ).

Function sum (x, y) {
var sum = x + y;
document.write(sum);
}
sum(5, 4);

Код достаточно прозрачный, однако, давайте прокомментирую. Опять ключевое слово function , потом название функции (в данном случае, пусть будет sum ). Внутри скобок указал два параметра, которые требуются (x и y ). Внутри функции я создаю ещё одну переменную sum (это совершенно нормально называть переменные и функции одинаково), которой присваиваю сумму x и y (которые были переданы). И затем вывожу в окно браузера полученный результат. После функции вызываю её, передав параметры 5 и 4 . Вы можете проверить, и увидите в окне браузера - 9 .

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

Function sum(x, y) {
var sum = x + y;
return sum;
}
var z = sum(4, 5) + sum(1,-3);
document.write(z);

Обратите внимание на ключевое слово return . Оно возвращает результат (в нашем случае - сумму двух чисел). Таким образом, sum(4,5) возвращает 9 . Это число мы складываем с результатом работы функции sum(1, -3) , то есть -2 . В итоге мы получим 7 . И только потом печатаем результат в браузере.

Надеюсь, Вы оценили возможности функций, поэтому создавать и использовать функции в JavaScript надо обязательно. И сейчас я сделаю один важный вывод, принцип, которому надо всегда следовать: любой повторяющийся код - необходимо выделять в отдельную функцию . Если у Вас 20 раз выводится одинаковые 5 строк (к примеру), то необходимо эти 5 строк выделить в отдельную функцию. Тем самым Вы вместо 100 строк (20 раз * 5 строк), напишите только 20 строк, да ещё и более понятных (название функции - это гораздо проще, чем 5 строк кода). Хочется сказать, что если этому правилу не следовать, то размер программы может увеличиться в десятки, а, может, и в сотни раз.

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

Functions are one of the fundamental building blocks in JavaScript. A function is a JavaScript procedure-a set of statements that performs a task or calculates a value. To use a function, you must define it somewhere in the scope from which you wish to call it.

A method is a function that is a property of an object. Read more about objects and methods in Working with objects .

Calling functions

Defining a function does not execute it. Defining the function simply names the function and specifies what to do when the function is called. Calling the function actually performs the specified actions with the indicated parameters. For example, if you define the function square , you could call it as follows:

Square(5);

The preceding statement calls the function with an argument of 5. The function executes its statements and returns the value 25.

Functions must be in scope when they are called, but the function declaration can be hoisted (appear below the call in the code), as in this example:

Console.log(square(5)); /* ... */ function square(n) { return n * n; }

The scope of a function is the function in which it is declared, or the entire program if it is declared at the top level.

Note: This works only when defining the function using the above syntax (i.e. function funcName(){}). The code below will not work. That means, function hoisting only works with function declaration and not with function expression.

Console.log(square); // square is hoisted with an initial value undefined. console.log(square(5)); // TypeError: square is not a function var square = function(n) { return n * n; }

The arguments of a function are not limited to strings and numbers. You can pass whole objects to a function. The show_props() function (defined in ) is an example of a function that takes an object as an argument.

A function can call itself. For example, here is a function that computes factorials recursively:

Function factorial(n) { if ((n === 0) || (n === 1)) return 1; else return (n * factorial(n - 1)); }

You could then compute the factorials of one through five as follows:

Var a, b, c, d, e; a = factorial(1); // a gets the value 1 b = factorial(2); // b gets the value 2 c = factorial(3); // c gets the value 6 d = factorial(4); // d gets the value 24 e = factorial(5); // e gets the value 120

There are other ways to call functions. There are often cases where a function needs to be called dynamically, or the number of arguments to a function vary, or in which the context of the function call needs to be set to a specific object determined at runtime. It turns out that functions are, themselves, objects, and these objects in turn have methods (see the Function object). One of these, the apply() method, can be used to achieve this goal.

Function scope

Variables defined inside a function cannot be accessed from anywhere outside the function, because the variable is defined only in the scope of the function. However, a function can access all variables and functions defined inside the scope in which it is defined. In other words, a function defined in the global scope can access all variables defined in the global scope. A function defined inside another function can also access all variables defined in its parent function and any other variable to which the parent function has access.

// The following variables are defined in the global scope var num1 = 20, num2 = 3, name = "Chamahk"; // This function is defined in the global scope function multiply() { return num1 * num2; } multiply(); // Returns 60 // A nested function example function getScore() { var num1 = 2, num2 = 3; function add() { return name + " scored " + (num1 + num2); } return add(); } getScore(); // Returns "Chamahk scored 5"

Scope and the function stack Recursion

A function can refer to and call itself. There are three ways for a function to refer to itself:

  • the function"s name
  • an in-scope variable that refers to the function
  • For example, consider the following function definition:

    Var foo = function bar() { // statements go here };

    Within the function body, the following are all equivalent:

  • bar()
  • arguments.callee()
  • foo()
  • A function that calls itself is called a recursive function . In some ways, recursion is analogous to a loop. Both execute the same code multiple times, and both require a condition (to avoid an infinite loop, or rather, infinite recursion in this case). For example, the following loop:

    Var x = 0; while (x < 10) { // "x < 10" is the loop condition // do stuff x++; }

    can be converted into a recursive function and a call to that function:

    Function loop(x) { if (x >= 10) // "x >= 10" is the exit condition (equivalent to "!(x < 10)") return; // do stuff loop(x + 1); // the recursive call } loop(0);

    However, some algorithms cannot be simple iterative loops. For example, getting all the nodes of a tree structure (e.g. the DOM) is more easily done using recursion:

    Function walkTree(node) { if (node == null) // return; // do something with node for (var i = 0; i < node.childNodes.length; i++) { walkTree(node.childNodes[i]); } }

    Compared to the function loop , each recursive call itself makes many recursive calls here.

    It is possible to convert any recursive algorithm to a non-recursive one, but often the logic is much more complex and doing so requires the use of a stack. In fact, recursion itself uses a stack: the function stack.

    The stack-like behavior can be seen in the following example:

    Function foo(i) { if (i < 0) return; console.log("begin: " + i); foo(i - 1); console.log("end: " + i); } foo(3); // Output: // begin: 3 // begin: 2 // begin: 1 // begin: 0 // end: 0 // end: 1 // end: 2 // end: 3

    Nested functions and closures

    You can nest a function within a function. The nested (inner) function is private to its containing (outer) function. It also forms a closure . A closure is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).

    Since a nested function is a closure, this means that a nested function can "inherit" the arguments and variables of its containing function. In other words, the inner function contains the scope of the outer function.

    • The inner function can be accessed only from statements in the outer function.
    • The inner function forms a closure: the inner function can use the arguments and variables of the outer function, while the outer function cannot use the arguments and variables of the inner function.

    The following example shows nested functions:

    Function addSquares(a, b) { function square(x) { return x * x; } return square(a) + square(b); } a = addSquares(2, 3); // returns 13 b = addSquares(3, 4); // returns 25 c = addSquares(4, 5); // returns 41

    Since the inner function forms a closure, you can call the outer function and specify arguments for both the outer and inner function:

    Function outside(x) { function inside(y) { return x + y; } return inside; } fn_inside = outside(3); // Think of it like: give me a function that adds 3 to whatever you give // it result = fn_inside(5); // returns 8 result1 = outside(3)(5); // returns 8

    Preservation of variables

    Notice how x is preserved when inside is returned. A closure must preserve the arguments and variables in all scopes it references. Since each call provides potentially different arguments, a new closure is created for each call to outside. The memory can be freed only when the returned inside is no longer accessible.

    This is not different from storing references in other objects, but is often less obvious because one does not set the references directly and cannot inspect them.

    Multiply-nested functions

    Functions can be multiply-nested, i.e. a function (A) containing a function (B) containing a function (C). Both functions B and C form closures here, so B can access A and C can access B. In addition, since C can access B which can access A, C can also access A. Thus, the closures can contain multiple scopes; they recursively contain the scope of the functions containing it. This is called scope chaining . (Why it is called "chaining" will be explained later.)

    Consider the following example:

    Function A(x) { function B(y) { function C(z) { console.log(x + y + z); } C(3); } B(2); } A(1); // logs 6 (1 + 2 + 3)

    In this example, C accesses B "s y and A "s x . This can be done because:

  • B forms a closure including A , i.e. B can access A "s arguments and variables.
  • C forms a closure including B .
  • Because B "s closure includes A , C "s closure includes A , C can access both B and A "s arguments and variables. In other words, C chains the scopes of B and A in that order.
  • The reverse, however, is not true. A cannot access C , because A cannot access any argument or variable of B , which C is a variable of. Thus, C remains private to only B .

    Name conflicts

    When two arguments or variables in the scopes of a closure have the same name, there is a name conflict . More inner scopes take precedence, so the inner-most scope takes the highest precedence, while the outer-most scope takes the lowest. This is the scope chain. The first on the chain is the inner-most scope, and the last is the outer-most scope. Consider the following:

    Function outside() { var x = 5; function inside(x) { return x * 2; } return inside; } outside()(10); // returns 20 instead of 10

    The name conflict happens at the statement return x and is between inside "s parameter x and outside "s variable x . The scope chain here is { inside , outside , global object}. Therefore inside "s x takes precedences over outside "s x , and 20 (inside "s x) is returned instead of 10 (outside "s x).

    Closures

    Closures are one of the most powerful features of JavaScript. JavaScript allows for the nesting of functions and grants the inner function full access to all the variables and functions defined inside the outer function (and all other variables and functions that the outer function has access to). However, the outer function does not have access to the variables and functions defined inside the inner function. This provides a sort of encapsulation for the variables of the inner function. Also, since the inner function has access to the scope of the outer function, the variables and functions defined in the outer function will live longer than the duration of the outer function execution, if the inner function manages to survive beyond the life of the outer function. A closure is created when the inner function is somehow made available to any scope outside the outer function.

    Var pet = function(name) { // The outer function defines a variable called "name" var getName = function() { return name; // The inner function has access to the "name" variable of the outer //function } return getName; // Return the inner function, thereby exposing it to outer scopes } myPet = pet("Vivie"); myPet(); // Returns "Vivie"

    It can be much more complex than the code above. An object containing methods for manipulating the inner variables of the outer function can be returned.

    Var createPet = function(name) { var sex; return { setName: function(newName) { name = newName; }, getName: function() { return name; }, getSex: function() { return sex; }, setSex: function(newSex) { if(typeof newSex === "string" && (newSex.toLowerCase() === "male" || newSex.toLowerCase() === "female")) { sex = newSex; } } } } var pet = createPet("Vivie"); pet.getName(); // Vivie pet.setName("Oliver"); pet.setSex("male"); pet.getSex(); // male pet.getName(); // Oliver

    In the code above, the name variable of the outer function is accessible to the inner functions, and there is no other way to access the inner variables except through the inner functions. The inner variables of the inner functions act as safe stores for the outer arguments and variables. They hold "persistent" and "encapsulated" data for the inner functions to work with. The functions do not even have to be assigned to a variable, or have a name.

    Var getCode = (function() { var apiCode = "0]Eal(eh&2"; // A code we do not want outsiders to be able to modify... return function() { return apiCode; }; })(); getCode(); // Returns the apiCode

    There are, however, a number of pitfalls to watch out for when using closures. If an enclosed function defines a variable with the same name as the name of a variable in the outer scope, there is no way to refer to the variable in the outer scope again.

    Var createPet = function(name) { // The outer function defines a variable called "name". return { setName: function(name) { // The enclosed function also defines a variable called "name". name = name; // How do we access the "name" defined by the outer function? } } }

    Using the arguments object

    The arguments of a function are maintained in an array-like object. Within a function, you can address the arguments passed to it as follows:

    Arguments[i]

    where i is the ordinal number of the argument, starting at zero. So, the first argument passed to a function would be arguments . The total number of arguments is indicated by arguments.length .

    Using the arguments object, you can call a function with more arguments than it is formally declared to accept. This is often useful if you don"t know in advance how many arguments will be passed to the function. You can use arguments.length to determine the number of arguments actually passed to the function, and then access each argument using the arguments object.

    For example, consider a function that concatenates several strings. The only formal argument for the function is a string that specifies the characters that separate the items to concatenate. The function is defined as follows:

    Function myConcat(separator) { var result = ""; // initialize list var i; // iterate through arguments for (i = 1; i < arguments.length; i++) { result += arguments[i] + separator; } return result; }

    You can pass any number of arguments to this function, and it concatenates each argument into a string "list":

    // returns "red, orange, blue, " myConcat(", ", "red", "orange", "blue"); // returns "elephant; giraffe; lion; cheetah; " myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); // returns "sage. basil. oregano. pepper. parsley. " myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");

    Note: The arguments variable is "array-like", but not an array. It is array-like in that it has a numbered index and a length property. However, it does not possess all of the array-manipulation methods.

    Two factors influenced the introduction of arrow functions: shorter functions and non-binding of this .

    Shorter functions

    In some functional patterns, shorter functions are welcome. Compare:

    Var a = [ "Hydrogen", "Helium", "Lithium", "Beryllium" ]; var a2 = a.map(function(s) { return s.length; }); console.log(a2); // logs var a3 = a.map(s => s.length); console.log(a3); // logs

    No separate this

    Until arrow functions, every new function defined its own value (a new object in the case of a constructor, undefined in function calls, the base object if the function is called as an "object method", etc.). This proved to be less than ideal with an object-oriented style of programming.

    Function Person() { // The Person() constructor defines `this` as itself. this.age = 0; setInterval(function growUp() { // In nonstrict mode, the growUp() function defines `this` // as the global object, which is different from the `this` // defined by the Person() constructor. this.age++; }, 1000); } var p = new Person();

    In ECMAScript 3/5, this issue was fixed by assigning the value in this to a variable that could be closed over.

    Function Person() { var self = this; // Some choose `that` instead of `self`. // Choose one and be consistent. self.age = 0; setInterval(function growUp() { // The callback refers to the `self` variable of which // the value is the expected object. self.age++; }, 1000); }

    • Перевод

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

    На первых этапах изучения JavaScript новички обычно думают, что функции в нем работают примерно так же, как, скажем, в C#. Но механизмы вызова функций в JavaScript имеют ряд важных отличий, и незнание их может вылиться в ошибки, которые будет непросто найти.

    Давайте напишем простую функцию, которая возвращает массив из трех элементов - текущего значения this и двух аргументов, переданных в функцию.
    function makeArray(arg1, arg2){ return [ this, arg1, arg2 ]; }

    Самый распространенный способ: глобальный вызов Новички часто объявляют функции так, как показано в примере выше. Вызвать эту функцию не составляет труда:
    makeArray("one", "two"); // => [ window, "one", "two" ]
    Погодите. Откуда взялся объект window ? Почему это у нас this равен window ?

    В JavaScript, неважно, выполняется ли скрипт в браузере или в ином окружении, всегда определен глобальный объект . Любой код в нашем скрипте, не «привязанный» к чему-либо (т.е. находящийся вне объявления объекта) на самом деле находится в контексте глобального объекта. В нашем случае, makeArray - не просто функция, «гуляющая» сама по себе. На самом деле, makeArray - метод глобального объекта (в случае исполнения кода в браузере) window . Доказать это легко:
    alert(typeof window.methodThatDoesntExist); // => undefined alert(typeof window.makeArray); // => function
    То есть вызов makeArray("one", "two"); равносилен вызову window.makeArray("one", "two"); .

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

    Правило вызова функций №1: Если функция вызывается напрямую, без указания объекта (например, myFunction()), значением this будет глобальный объект (window в случае исполнения кода в браузере).

    Вызов метода Давайте создадим простой объект и сделаем makeArray его методом. Объект объявим с помощью литеральной нотации, а после вызовем наш метод:
    // создаем объект var arrayMaker = { someProperty: "какое-то значение", make: makeArray }; // вызываем метод make() arrayMaker.make("one", "two"); // => [ arrayMaker, "one", "two" ] // альтернативный синтаксис, используем квадратные скобки arrayMaker["make"]("one", "two"); // => [ arrayMaker, "one", "two" ]
    Видите разницу? Значение this в этом случае - сам объект. Почему не window , как в предыдущем случае, ведь объявление функции не изменилось? Весь секрет в том, как передаются функции в JavaScript. Function - это стандартный тип JavaScript, являющийся на самом деле объектом, и как и любой другой объект, функции можно передавать и копировать. В данном случае, мы как бы скопировали всю функцию, включая список аргументов и тело, и присвоили получившийся объект свойству make объекта arrayMaker . Это равносильно такому объявлению:
    var arrayMaker = { someProperty: "Какое-то значение"; make: function (arg1, arg2) { return [ this, arg1, arg2]; } };
    Правило вызова функций №2: В функции, вызванной с использованием синтаксиса вызова метода, например, obj.myFunction() или obj["myFunction"]() , this будет иметь значение obj .

    Непонимание этого простого, в общем-то, принципа часто приводит к ошибкам при обработке событий:
    function buttonClicked(){ var text = (this === window) ? "window" : this.id; alert(text); } var button1 = document.getElementById("btn1"); var button2 = document.getElementById("btn2"); button1.onclick = buttonClicked; button2.onclick = function(){ buttonClicked(); };
    Щелчок по первой кнопке покажет сообщение «btn1» , потому что в данном случае мы вызываем функцию как метод, и this внутри функции получит значение объекта, которому этот метод принадлежит. Щелчок по второй кнопке выдаст «window» , потому что в этом случае мы вызываем buttonClicked напрямую (т.е. не как obj.buttonClicked()). То же самое происходит, когда мы назначаем обработчик события в тэге элемента, как в случае третьей кнопки. Щелчок по третьей кнопке покажет то же самое сообщение, что и для второй.

    При использовании библиотек вроде jQuery думать об этом не надо. jQuery позаботится о том, чтобы переписать значение this в обработчике события так, чтобы значением this был элемент, вызвавший событие:
    // используем jQuery $("#btn1").click(function() { alert(this.id); // jQuery позаботится о том, чтобы "this" являлась кнопкой });
    Каким образом jQuery удается изменить значение this ? Читайте ниже.

    Еще два способа: apply() и call() Логично, что чем чаще вы используете функции, тем чаще вам приходится передавать их и вызывать в разных контекстах. Зачастую возникает необходимость переопределить значение this . Если вы помните, функции в JavaScript являются объектами. На практике это означает, что у функций есть предопределенные методы. apply() и call() - два из них. Они позволяют переопределять значение this:
    var car = { year: 2008, model: "Dodge Bailout" }; makeArray.apply(car, [ "one", "two" ]); // => [ car, "one", "two" ] makeArray.call(car, "one", "two"); // => [ car, "one", "two" ]
    Эти два метода очень похожи. Первый параметр переопределяет this . Различия между ними заключаются в последющих аргументах: Function.apply() принимает массив значений, которые будут переданы функции, а Function.call() принимает аргументы раздельно. На практике, по моему мнению, удобнее применять apply() .

    Правило вызова функций №3: Если требуется переопределить значение this , не копируя функцию в другой объект, можно использовать myFunction.apply(obj) или myFunction.call(obj) .

    Конструкторы Я не буду подробно останавливаться на объявлении собственных типов в JavaScript, но считаю необходимым напомнить, что в JavaScript нет классов, а любой пользовательский тип нуждается в конструкторе. Кроме того, методы пользовательского типа лучше объявлять через prototype , который является свойством фукции-конструктора. Давайте создадим свой тип:
    // объявляем конструктор function ArrayMaker(arg1, arg2) { this.someProperty = "неважно"; this.theArray = [ this, arg1, arg2 ]; } // объявляем методы ArrayMaker.prototype = { someMethod: function () { alert("Вызван someMethod"); }, getArray: function () { return this.theArray; } }; var am = new ArrayMaker("one", "two"); var other = new ArrayMaker("first", "second"); am.getArray(); // => [ am, "one", "two" ]
    Важным в этом примере является наличие оператора new перед вызовом функции. Если бы не он, это был бы глобальный вызов, и создаваемые в конструкторе свойства относились бы к глобальному объекту. Нам такого не надо. Кроме того, в конструкторах обычно не возвращают значения явно. Без оператора new конструктор вернул бы undefined , с ним он возвращает this . Хорошим стилем считается наименование конструкторов с заглавной буквы; это позволит вспомнить о необходимости оператора new .

    В остальном, код внутри конструктора, скорее всего, будет похож на код, который вы написали бы на другом языке. Значение this в данном случае - это новый объект, который вы создаете.

    Правило вызова функций №4: При вызове функции с оператором new , значением this будет новый объект, созданный средой исполнения JavaScript. Если эта функция не возвращает какой-либо объект явно, будет неявно возвращен this .

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

    Функции - ключевая концепция в JavaScript. Важнейшей особенностью языка является первоклассная поддержка функций ​ (functions as first-class citizen) . Любая функция это объект, и следовательно ею можно манипулировать как объектом, в частности:

    • передавать как аргумент и возвращать в качестве результата при вызове других функций (функций высшего порядка);
    • создавать анонимно и присваивать в качестве значений переменных или свойств объектов.

    Это определяет высокую выразительную мощность JavaScript и позволяет относить его к числу языков, реализующих функциональную парадигму программирования (что само по себе есть очень круто по многим соображениям).

    Функция в JavaScript специальный тип объектов, позволяющий формализовать средствами языка определённую логику поведения и обработки данных.

    Для понимания работы функций необходимо (и достаточно?) иметь представление о следующих моментах:

    Объявление функций Функции вида "function declaration statement"

    Объявление функции (function definition , или function declaration , или function statement ) состоит из ключевого слова function и следующих частей:

    • Имя функции.
    • Список параметров (принимаемых функцией) заключенных в круглые скобки () и разделенных запятыми.
    • Инструкции, которые будут выполненны после вызова функции, заключают в фигурные скобки { } .

    Например, следующий код объявляет простую функцию с именим square:

    Function square(number) { return number * number; }

    Функция square принимает один параметр, названный number. Состоит из одной инструкции, которая означает вернуть параметр этой функции (это number) умноженный на самого себя. Инструкция return указывает на значение, которые будет возвращено функцией.

    Return number * number;

    Примитивные параметры (например, число) передаются функции значением; значение передаётся в функцию, но если функция меняет значение параметра, это изменение не отразится глобально или после вызова функции.

    Если Вы передадите объект как параметр (не примитив, например, или определяемые пользователем объкты), и функция изменит свойство переданного в неё объекта, это изменение будет видно и вне функции, как показано в следующим примере:

    Function myFunc(theObject) { theObject.make = "Toyota"; } var mycar = {make: "Honda", model: "Accord", year: 1998}; var x, y; x = mycar.make; // x получает значение "Honda" myFunc(mycar); y = mycar.make; // y получает значение "Toyota" // (свойство было изменено функцией)

    Функции вида "function definition expression"

    Функция вида "function declaration statement" по синтаксису является инструкцией (statement ), ещё функция может быть вида "function definition expression". Такая функция может быть анонимной (она не имеет имени). Например, функция square может быть вызвана так:

    Var square = function(number) { return number * number; }; var x = square(4); // x получает значение 16

    Однако, имя может быть и присвоено для вызова самой себя внутри самой функции и для отладчика (debugger ) для идентифицирования функции в стек-треках (stack traces ; "trace" - "след" / "отпечаток").

    Var factorial = function fac(n) { return n < 2 ? 1: n * fac(n - 1); }; console.log(factorial(3));

    Функции вида "function definition expression" удобны, когда функция передается аргументом другой функции. Следующий пример показывает функцию map , которая должна получить функцию первым аргументом и массив вторым.

    Function map(f, a) { var result = , // Create a new Array i; for (i = 0; i != a.length; i++) result[i] = f(a[i]); return result; }

    В следующим коде наша функция принимает функцию, которая является function definition expression, и выполняет его для каждого элемента принятого массива вторым аргументом.

    Function map(f, a) { var result = ; // Create a new Array var i; // Declare variable for (i = 0; i != a.length; i++) result[i] = f(a[i]); return result; } var f = function(x) { return x * x * x; } var numbers = ; var cube = map(f,numbers); console.log(cube);

    Функция возвращает: .

    В JavaScript функция может быть объявлена с условием. Например, следующая функция будет присвоена переменной myFunc только, если num равно 0:

    Var myFunc; if (num === 0) { myFunc = function(theObject) { theObject.make = "Toyota"; } }

    В дополнение к объявлениям функций, описанных здесь, Вы также можете использовать конструктор Function для создания функций из строки во время выполнения (runtime ), подобно .

    Метод - это функция, которая является свойством объекта. Узнать больше про объекты и методы можно по ссылке: Работа с объектами .

    Вызовы функций

    Объявление функции не выполняет её. Объявление функции просто называет функцию и указывает, что делать при вызове функции. Вызов функции фактически выполняет указанные действия с указанными параметрами. Например, если Вы определите функцию square , Вы можете вызвать её следующим образом:

    Square(5);

    Эта инструкция вызывает функцию с аргументом 5. Функция вызывает свои инструкции и возвращает значение 25.

    Функции могут быть в области видимости, когда они уже определены, но функции вида "function declaration statment" могут быть подняты (поднятие - hoisting ), также как в этом примере:

    Console.log(square(5)); /* ... */ function square(n) { return n * n; }

    Область видимости функции - функция, в котором она определена, или целая программа, если она объявлена по уровню выше.

    Примечание: Это работает только тогда, когда объявлении функции использует вышеупомянутый синтаксис (т.е. function funcName(){}). Код ниже не будет работать. Имеется в виду то, что поднятие функции работает только с function declaration и не работает с function expression.

    Console.log(square); // square поднят со значением undefined. console.log(square(5)); // TypeError: square is not a function var square = function(n) { return n * n; }

    Аргументы функции не ограничиваются строками и числами. Вы можете передавать целые объекты в функцию. Функция show_props() (объявленная в Работа с объектами) является примером функции, принимающей объекты аргументом.

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

    Function factorial(n) { if ((n === 0) || (n === 1)) return 1; else return (n * factorial(n - 1)); }

    Затем вы можете вычислить факториалы от одного до пяти следующим образом:

    Var a, b, c, d, e; a = factorial(1); // a gets the value 1 b = factorial(2); // b gets the value 2 c = factorial(3); // c gets the value 6 d = factorial(4); // d gets the value 24 e = factorial(5); // e gets the value 120

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

    Область видимости функций

    (function scope)

    Переменные объявленные в функции не могут быть доступными где-нибудь вне этой функции, поэтому переменные (которые нужны именно для функции) объявляют только в scope функции. При этом функция имеет доступ ко всем переменным и функциям, объявленным внутри её scope. Другими словами функция объявленная в глобальном scope имеет доступ ко всем переменным в глобальном scope. Функция объявленная внутри другой функции ещё имеет доступ и ко всем переменным её родителькой функции и другим переменным, к которым эта родительская функция имеет доступ.

    // Следующие переменные объявленны в глобальном scope var num1 = 20, num2 = 3, name = "Chamahk"; // Эта функция объявленна в глобальном scope function multiply() { return num1 * num2; } multiply(); // вернет 60 // Пример вложенной функции function getScore() { var num1 = 2, num2 = 3; function add() { return name + " scored " + (num1 + num2); } return add(); } getScore(); // вернет "Chamahk scored 5"

    Scope и стек функции

    (function stack)

    Рекурсия

    Функция может вызывать саму себя. Три способа такого вызова:

  • по имени функции
  • по переменной, которая ссылается на функцию
  • Для примера рассмотрим следующие функцию:

    Var foo = function bar() { // statements go here };

    Внутри функции (function body ) все следующие вызовы эквивалентны:

  • bar()
  • arguments.callee()
  • foo()
  • Функция, которая вызывает саму себя, называется рекурсивной функцией (recursive function ). Получается, что рекурсия аналогична циклу (loop ). Оба вызывают некоторый код несколько раз, и оба требуют условия (чтобы избежать бесконечного цикла, вернее бесконечной рекурсии). Например, следующий цикл:

    Var x = 0; while (x < 10) { // "x < 10" - это условие для цикла // do stuff x++; }

    можно было изменить на рекурсивную функцию и вызовом этой функции:

    Function loop(x) { if (x >= 10) // "x >= 10" - это условие для конца выполения (тоже самое, что "!(x < 10)") return; // делать что-то loop(x + 1); // рекурсионный вызов } loop(0);

    Однако некоторые алгоритмы не могут быть простыми повторяющимися циклами. Например, получение всех элементов структуры дерева (например, ) проще всего реализуется использованием рекурсии:

    Function walkTree(node) { if (node == null) // return; // что-то делаем с элементами for (var i = 0; i < node.childNodes.length; i++) { walkTree(node.childNodes[i]); } }

    В сравнении с функцией loop , каждый рекурсивный вызов сам вызывает много рекурсивных вызовов.

    Также возможно превращение некоторых рекурсивных алгоритмов в нерекурсивные, но часто их логика очень сложна, и для этого потребуется использование стека (stack ). По факту рекурсия использует stach: function stack.

    Поведение stack"а можно увидеть в следующем примере:

    Function foo(i) { if (i < 0) return; console.log("begin: " + i); foo(i - 1); console.log("end: " + i); } foo(3); // Output: // begin: 3 // begin: 2 // begin: 1 // begin: 0 // end: 0 // end: 1 // end: 2 // end: 3

    Вложенные функции (nested functions) и замыкания (closures)

    Вы можете вложить одну функцию в другую. Вложенная функция (nested function ; inner ) приватная (private ) и она помещена в другую функцию (outer ). Так образуется замыкание (closure ). Closure - это выражение (обычно функция), которое может иметь свободные переменные вместе со средой, которая связывает эти переменые (что "закрывает" ("close" ) выражение).

    Поскольку вложенная функция это closure, это означает, что вложенная функция может "унаследовать" (inherit ) аргументы и переменные функции, в которую та вложена. Другими словами, вложенная функция содержит scope внешней ("outer" ) функции.

    Подведем итог:

    • Вложенная функция имеет доступ ко всем инструкциям внешней функции.
    • Вложенная функция формирует closure: она может использовать аргументы и переменные внешней функции, в то время как внешняя функция не может использовать аргументы и переменные вложенной функции.

    Следующий пример показывает вложенную функцию:

    Function addSquares(a, b) { function square(x) { return x * x; } return square(a) + square(b); } a = addSquares(2, 3); // возвращает 13 b = addSquares(3, 4); // возвращает 25 c = addSquares(4, 5); // возвращает 41

    Поскольку вложенная функция формирует closure, Вы можете вызвать внешную функцию и указать аргументы для обоих функций (для outer и innner).

    Function outside(x) { function inside(y) { return x + y; } return inside; } fn_inside = outside(3); // Подумайте над этим: дайте мне функцию, // который передай 3 result = fn_inside(5); // возвращает 8 result1 = outside(3)(5); // возвращает 8

    Сохранение переменных

    Обратите внимание, значение x сохранилось, когда возвращалось inside . Closure должно сохранять аргументы и переменные во всем scope. Поскольку каждый вызов предоставляет потенциально разные аргументы, создается новый closure для каждого вызова во вне. Память может быть очищена только тогда, когда inside уже возвратился и больше не доступен.

    Это не отличается от хранения ссылок в других объектах, но часто менее очевидно, потому что не устанавливаются ссылки напрямую и нельзя посмотреть там.

    Несколько уровней вложенности функций (Multiply-nested functions)

    Функции можно вкадывать несколько раз, т.е. функция (A) хранит в себе функцию (B), которая хранит в себе функцию (C). Обе фукнкции B и C формируют closures, так B имеет доступ к переменным и аргументам A, и C имеет такой же доступ к B. В добавок, поскольку C имеет такой доступ к B, который имеет такой же доступ к A, C ещё имеет такой же доспут к A. Таким образом cloures может хранить в себе несколько scope; они рекурсивно хранят scope функций, содержащих его. Это называется chaining (chain - цепь ; Почему названо "chaining" будет объяснено позже)

    Рассмотрим следующий пример:

    Function A(x) { function B(y) { function C(z) { console.log(x + y + z); } C(3); } B(2); } A(1); // в консоле выведится 6 (1 + 2 + 3)

    В этом примере C имеет доступ к y функции B и к x функции A . Так получается, потому что:

  • Функция B формирует closure, включающее A , т.е. B имеет доступ к аргументам и переменным функции A .
  • Функция C формирует closure, включающее B .
  • Раз closure функции B включает A , то closure С тоже включает A, C имеет доступ к аргументам и переменным обоих функций B и A . Другими словами, С cвязывает цепью (chain ) scopes функций B и A в таком порядке.
  • В обратном порядке, однако, это не верно. A не имеет доступ к переменным и аргументам C , потому что A не имеет такой доступ к B . Таким образом, C остается приватным только для B .

    Конфликты имен (Name conflicts)

    Когда два аргумента или переменных в scope у closure имеют одинаковые имена, происходит конфликт имени (name conflict ). Более вложенный (more inner ) scope имеет приоритет, так самый вложенный scope имеет наивысший приоритет, и наоборот. Это цепочка областей видимости (scope chain ). Самым первым звеном является самый глубокий scope, и наоборот. Рассмотрим следующие:

    Function outside() { var x = 5; function inside(x) { return x * 2; } return inside; } outside()(10); // возвращает 20 вместо 10

    Конфликт имени произошел в инструкции return x * 2 между параметром x функции inside и переменной x функции outside . Scope chain здесь будет таким: { inside ==> outside ==> глобальный объект (global object )}. Следовательно x функции inside имеет больший приоритет по сравнению с outside , и нам вернулось 20 (= 10 * 2), а не 10 (= 5 * 2).

    Замыкания

    (Closures)

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

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

    Также, поскольку вложенная функция имеет доступ к scope внешней функции, переменные и функции, объявленные во внешней функции, будет продолжать существовать и после её выполнения для вложенной функции, если на них и на неё сохранился доступ (имеется ввиду, что переменные, объявленные во внешней функции, сохраняются, только если внутренняя функция обращается к ним).

    Closure создается, когда вложенная функция как-то стала доступной в неком scope вне внешней функции.

    Var pet = function(name) { // Внешняя функция объявила переменную "name" var getName = function() { return name; // Вложенная функция имеет доступ к "name" внешней функции } return getName; // Возвращаем вложенную функцию, тем самым сохраняя доступ // к ней для другого scope } myPet = pet("Vivie"); myPet(); // Возвращается "Vivie", // т.к. даже после выполнения внешней функции // name сохранился для вложенной функции

    Более сложный пример представлен ниже. Объект с методами для манипуляции вложенной функции внешней функцией можно вернуть (return ).

    Var createPet = function(name) { var sex; return { setName: function(newName) { name = newName; }, getName: function() { return name; }, getSex: function() { return sex; }, setSex: function(newSex) { if(typeof newSex === "string" && (newSex.toLowerCase() === "male" || newSex.toLowerCase() === "female")) { sex = newSex; } } } } var pet = createPet("Vivie"); pet.getName(); // Vivie pet.setName("Oliver"); pet.setSex("male"); pet.getSex(); // male pet.getName(); // Oliver

    В коде выше переменная name внешней функции доступна для вложенной функции, и нет другого способа доступа к вложенным переменным кроме как через вложенную функцию. Вложенные переменные вложенной функции являются безопасными хранилищами для внешних аргументов и переменных. Они содержат "постоянные" и "инкапсулированные" данные для работы с ними вложенными функциями. Функции даже не должны присваиваться переменной или иметь имя.

    Var getCode = (function() { var apiCode = "0]Eal(eh&2"; // A code we do not want outsiders to be able to modify... return function() { return apiCode; }; }()); getCode(); // Returns the apiCode

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

    Var createPet = function(name) { // The outer function defines a variable called "name". return { setName: function(name) { // The enclosed function also defines a variable called "name". name = name; // How do we access the "name" defined by the outer function? } } }

    Использование объекта arguments

    Объект arguments функции является псевдо-массивом. Внутри функции Вы можете ссылаться к аргументам следующим образом:

    Arguments[i]

    где i - это порядковый номер аргумента, отсчитывающийся с 0. К первому аргументу, переданному функции, обращаются так arguments . А получить количество всех аргументов - arguments.length .

    С помощью объекта arguments Вы можете вызвать функцию, передавая в неё больше аргументов, чем формально объявили принять. Это очень полезно, если Вы не знаете точно, сколько аргументов должна принять Ваша функция. Вы можете использовать arguments.length для определения количества аргументов, переданных функции, а затем получить доступ к каждому аргументу, используя объект arguments .

    Для примера рассмотрим функцию, которая конкатенирует несколько строк. Единственным формальным аргументом для функции будет строка, которая указывает символы, которые разделяют элементы для конкатенации. Функция определяется следующим образом:

    Function myConcat(separator) { var result = ""; var i; // iterate through arguments for (i = 1; i < arguments.length; i++) { result += arguments[i] + separator; } return result; }

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

    // возвращает "red, orange, blue, " myConcat(", ", "red", "orange", "blue"); // возвращает "elephant; giraffe; lion; cheetah; " myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); // возвращает "sage. basil. oregano. pepper. parsley. " myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");

    Т.к. arguments является псевдо-массивом, к нему применимы некоторые методы массивов, например, for .. in

    Function func() { for (value in arguments){ console.log(value); } } func(1, 2, 3); // 1 // 2 // 3

    Примечание: arguments является псевдо-массивом, но не массивом. Это псевдо-массив, в котором есть пронумерованные индексы и свойство length . Однако он не обладает всеми методами массивов.

    Оставшиеся параметры (Rest parameters)

    На введение стрелочных функций повлияли два фактора: более короткие функции и лексика this .

    Более короткие функции

    В некоторый функциональных паттернах приветствуется использование более коротких функций. Сравните:

    Var a = [ "Hydrogen", "Helium", "Lithium", "Beryllium" ]; var a2 = a.map(function(s) { return s.length; }); console.log(a2); // logs var a3 = a.map(s => s.length); console.log(a3); // logs

    Лексика this

    До стрелочных функций каждая новая функция определяла свое значение this (новый объект в случае конструктора, undefined в strict mode, контекстный объект, если функция вызвана как метод объекта, и т.д.). Это оказалось раздражающим с точки зрения объектно-орентированного стиля программирования.

    Function Person() { // Конструктор Person() определяет `this` как самого себя. this.age = 0; setInterval(function growUp() { // Без strict mode функция growUp() определяет `this` // как global object, который отличается от `this` // определенного конструктором Person(). this.age++; }, 1000); } var p = new Person();

    В ECMAScript 3/5 эта проблема была исправлена путем присвоения значения this переменной, которую можно было бы замкнуть.

    Function Person() { var self = this; // Некоторые выбирают `that` вместо `self`. // Выберите что-то одно и будьте последовательны. self.age = 0; setInterval(function growUp() { // The callback refers to the `self` variable of which // the value is the expected object. self.age++; }, 1000); }

    Смотрите также Function в Справочнике JavaScript для получения дополнительной информации по функции как объекту.

    Статья в разработке!

    Статья, в которой рассмотрим, что такое функция, а также традиционный (классический) вариант работы с ней. Кроме этого, разберем, что такое аргументы (параметры) функции и оператор return.

    Что такое функция?

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

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

    Как организовать выполнение некоторой задачи в JavaScript с использованием функций? Чтобы это выполнить обычно поступают так:

    • разбивают задачу на составные части (подзадачи);
    • подзадачи оформляют через функции;
    • разрабатывают основной код с использованием вызова созданных функций.

    В результате такая программа становится более структурированной. В неё более просто вносить различные изменения и добавлять новые возможности.

    Объявление и вызов функции

    Операции с функцией в JavaScript можно разделить на 2 шага:

    • объявление (создание) функции.
    • вызов (выполнение) этой функции.

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

    // объявление функции someName function someName() { alert("Вы вызвали функцию someName!"); } JavaScript - Синтаксис объявления функции

    Функции такого вида в JavaScript называются function declaration statement . Кроме этого вида в JavaScript ещё различают функции function definition expression и arrow function expression .

    Составление имени функции выполняется по тем же правилам, что и имя переменной. Т.е. оно может содержать буквы, цифры (0-9), знаки «$» и «_». В качестве букв рекомендуется использовать только буквы английского алфавита (a-z, A-Z). Имя функции, также как и имя переменной не может начинаться с цифры.

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

    Набор инструкций , заключенный в фигурные скобки - это код функции , который будет выполнен при её вызове .

    Вызов функции. Объявленная функция сама по себе выполняться не будет . Для того чтобы её запустить , её необходимо вызвать . Вызов функции осуществляется посредством указания её имени и двух круглых скобок. Внутри скобок при необходимости указываются аргументы.

    // вызов функции, приведённой в предыдущем примере someName(); JavaScript - Синтаксис вызова функции

    Является ли функция в JavaScript объектом?

    Функции в JavaScript являются объектами. В JavaScript вообще всё является объектами, кроме шести примитивных типов данных. А если функция является объектом, то ссылку на неё можно сохранить в переменную.

    // объявление функции someName function someName() { alert("Вы вызвали функцию someName!"); } var reference = someName;

    После этого вызвать функцию можно будет так:

    Reference();

    Параметры и аргументы функции

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

    // вызов функции sayWelcome с передачей ей двух аргументов sayWelcome("Иван", "Иванов"); // ещё один вызов функции sayWelcome с двумя аргументами sayWelcome("Петр", "Петров");

    Параметры функции – это один из способов в JavaScript, посредством которого можно обратиться к аргументам внутри функции. Описываются параметры функции на этапе её объявления в круглых скобках.

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

    // объявление функции sayWelcome, которая имеет два параметра function sayWelcome (userFirstName, userLastName) { // инструкция, выводящая в консоль значения параметров «userFirstName» и «userLastName» console.log("Добро пожаловать, " + userLastName + " " + userFirstName); }

    В языке JavaScript при вызове функции количество аргументов не обязательно должно совпадать с количеством параметров . Параметры, которым при вызове, не было установлено значение, будут равны undefined .

    Например , вызовем функцию из примера, приведённого выше, без указания одного и двух параметров:

    // вызов функции sayWelcome и передача ей одного аргумента sayWelcome("Петр"); // Добро пожаловать, undefined Петр // вызов функции sayWelcome без передачи ей аргументов sayWelcome(); // Добро пожаловать, undefined undefined

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

    // объявление функции function outputParam(param1, param2, param3) { console.log(param1 + "; " + param2 + "; " + param3); } // вызовы функции outputParam с передачей ей разного количества параметров outputParam("Дождь","Снег","Туман"); // Дождь; Снег; Туман outputParam(17); // 17; undefined; undefined outputParam(24,33); // 24; 33; undefined outputParam(); // undefined; undefined; undefined

    Другой способ обратиться к аргументам внутри функции – это использовать специальный объект arguments . Доступ к аргументам через arguments выполняется точно также как к элементам обычного массива, т.е. по их порядковым номерам. Таким образом, argument - позволит получить первый аргумент, arguments – второй аргумент и т.д.

    // объявление функции sum function sum(num1, num2) { /* num1 или arguments – получить значение 1 аргумента num2 или arguments – получить значение 2 аргумента */ var sum1 = num1 + num2, sum2 = arguments + arguments; return "Сумма, полученная 1 способом равна " + sum1 + "; сумма, полученная 2 способом равна " + sum2; } /* выведем результат функции sum в консоль 7 - первый аргумент (к нему можно обратиться как по имени num1, так и с помощью arguments) 4 - второй аргумент (к нему можно обратиться как по имени num2, так и с помощью arguments) */ console.log(sum(7,4));

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

    Кроме получения аргументов, объект arguments позволяет также узнать их количество. Выполняется это с помощью свойства length.

    Перебрать аргументы , переданные функции, можно, например, с помощью цикла for или for...of .

    // объявление функции sum function sum() { var i = 0; console.log("Вывод всех аргументов с помощью цикла for"); for (i; i < arguments.length; i++) { console.log(i + 1 + " аргумент равен " + arguments[i]); } console.log("Вывод всех аргументов с помощью цикла for...of"); for (arg of arguments) { console.log(arg); } } // вызов функции sum sum(7, 4, 3, 1);

    Функция, выводящая в консоль все переданные ей аргументы и их количество:

    // объявление функции function myFunction () { var i; console.log("Количество переданных параметров = " + arguments.length); // переберём все параметры с помощью цикла for for (i = 0; i < arguments.length; i++) { console.log(i + " параметр = " + arguments[i]); } } // вызовы функции myFunction myFunction(3, 7, 27, "JavaScript"); myFunction(); myFunction("Яблоки", "Груши", "Апельсины");

    Функция, выполняющая сложение все переданных ей аргументов (их количество заранее неизвестно):

    // объявление функции var myCalc = function() { // переберём все параметры с помощью цикла for var i, sum = 0; for (i = 0; i lt; arguments.length; i++) { sum += arguments[i]; } // возвратим в качестве результата сумму return sum; } //вызов функции (вывод в консоль) console.log(myCalc(4, 20, 17, -6));

    В результате, посредством объекта arguments можно реализовать в теле функции:

    • проверку количества переданных аргументов;
    • обработку какого угодного количества параметров.

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

    Function mainF(p1, p2) { function childF() { console.log("p1 = " + p1 + "; p2 = " + p2); } childF(); } mainF(3, 5); // p1 = 3; p2 = 5 mainF(4, 7); // p1 = 4; p2 = 7

    Значение параметров по умолчанию

    Начиная с версии ECMAScript 2015 (6) параметру функции можно задать значение, которое он будет иметь по умолчанию.

    Например , установим параметру «color» значение по умолчанию, равное «#009688»:

    Function setBGColor(color = "#009688") { document.body.style.backgroundColor = color; } setBGColor(); // цвет фона будет равен #009688 setBGColor("red"); // цвет фона будет равен red

    До ECMAScript 2015 задать параметру значение по умолчанию можно, например, было так:

    Function setBGColor(color) { color = color !== undefined ? color: "#009688"; // устанавливаем color значение по умолчанию, равное "#009688" document.body.style.backgroundColor = color; }

    Оставшиеся параметры (rest parameters)

    Если при вызове функции ей передать аргументов больше, чем у неё есть параметров, то получить оставшиеся можно с помощью, так называемых оставшихся параметров (rest patameters) . Данная возможность в языке появилась, начиная с ECMAScript 2015.

    // ...nums - оставшиеся параметры, к которым можно обратиться в данном случае по имени nums function doMath(mathAction, ...nums) { var result = 0; nums.forEach(function(value) { switch (mathAction) { case "sum": result += value; break; case "sumCube": result += value**3; break; case "sumSquare": result += value**2; break; deafult: result = 0; } }) return result; } console.log(doMath("sum", 3, 4, 21, -4)); // 24 (3 + 4 + 21 + (-4)) console.log(doMath("sumSquare", 1, 4)); // 17 (1^2 + 4^2) console.log(doMath("sumCube", 3, 2, 4)); // 99 (3^3 + 2^3 + 4^3)

    Оператор return

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

    Функция в JavaScript всегда возвращает результат в вне зависимости от того, используется ли оператор return или нет.

    // функция, возвращающая результат function sayWelcome (userFirstName, userLastName) { if ((!userFirstName) || (!userLastName)) return "Добро пожаловать, анонимный пользователь"; else return "Добро пожаловать, " + userLastName + " " + userFirstName; } // объявление переменной person var person; // присвоить переменной person результат функции sayWelcome person = sayWelcome("Иван","Иванов"); // вывести значение переменной в консоль console.log(person); //Инструкция, которая выведит в консоль результат работы функции sayWelcome console.log(sayWelcome("Петр","Петров")); //Инструкция, которая выведит в консоль результат работы функции sayWelcome console.log(sayWelcome("Сидоров")); JavaScript - Функция с проверкой параметров

    Функция в JavaScript в результате своего выполнения всегда возвращает результат, даже если он явно не определён с помощью оператора return. Этот результат значение undefined.

    // 1. функция, не возвращающая никакого результата function sayWelcome (userFirstName, userLastName) { console.log("Добро пожаловать, " + userLastName + " " + userFirstName); } // попробуем получить результат у функции, которая ничего не возвращает console.log(sayWelcome ("Иван", "Иванов")); // 2. функция, содержащая оператор return без значения function sayDay (day) { day = "Сегодня, " + day; return; //эта инструкция не выполнится, т.к. она идёт после оператора return console.log(day); } // попробуем получить результат у функции, которая содержит оператор return без значения console.log(sayDay("21 февраля 2016г.")); JavaScript - Получить значение у функции, которая ничего не возвращает

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

    Перегрузка функций в JavaScript

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

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

    Подобную функциональность можно реализовать в JavaScript используя следующие действия:

    • Для того чтобы проверить передан аргумент или нет, используйте условие с проверкой его значения на undefined .
    • Для проверки количества переданных аргументов функции используйте свойство объекта arguments length .
    • Чтобы узнать тип переданного значения аргумента используйте операторы typeof или instanceof .
    • Для работы с переменным числом аргументов, используйте объект arguments .
    • Начиная с версии ECMAScript6, Вы можете указывать значения по умолчанию для аргументов.

    Например, создадим функцию, при вызове которой можно указывать один или два аргумента:

    //объявление функции, которая изменяет цвет заднего фона элементов function setBgColor(bgColor,elements) { //если параметр elements при вызове не указан if (elements=== undefined) { //то приравнять его значение "div" elements = "div"; } //получить все элементы elements = $(elements); //перебрать все элементы и установить им указанный цвет заднего фона elements.each(function(){ $(this).css("background-color",bgColor); }); } /*Вызвать функцию setBgColor, указав один параметр. Т.к. 2 параметр не указан, то данная фукция изменит цвет заднего фона у всех элементов div.*/ setBgColor("green"); /*Вызвать функцию setBgColor, указав 2 параметра. Т.к. 2 параметр задан, то данная функция изменит цвет заднего фона только элементов button.*/ setBgColor("#ff0000","button");

    Произведём некоторые изменения в вышепредставленном коде. А именно, укажем для второго параметра значение по умолчанию:

    //объявление функции, которая изменяет цвет заднего фона элементов //параметр elements имеет значение "div" по умолчанию function setBgColor(bgColor,elements = "div") { //получить все элементы elements = $(elements); //перебрать все элементы и установить им указанный цвет заднего фона elements.each(function(){ $(this).css("background-color",bgColor); }); } //вызвать функцию setBgColor, указав один параметр setBgColor("green"); //вызвать функцию setBgColor, указав 2 параметра setBgColor("#ff0000","button");

    Пример, как в JavaScript можно реализовать «перегруженную» функцию, вычисляющую количество калорий, которых необходимо человеку в день:

    // описание функции function countCal(sex, height) { // параметры: sex (пол) и height (рост) var result; if ((sex === 0) || (sex === "man")) { result = (height - 100) * 20; } else if ((sex === 1) || (sex === "woman")) { result = (height - 105) * 19; } if (result) { // arguments - уровень активности if (arguments) { result *= arguments; } console.log("Количество ккал для нормальной жизнедеятельности: " + result); } else { console.log("Неверно указаны параметры"); } } /* вызов функции и передаче ей 2 аргументов (1 - "man", к нему можно обратиться с помощью имени sex и arguments; 2 - значение 185, к нему можно обратиться с помощью имени sex и arguments) */ countCal("man", 185); /* вызов функции и передаче ей 3 параметров, хотя в описании функции присутствуют только 2 (получить значение 3 параметра в данном случае можно только как arguments) */ countCal(0, 185, 2);

    Рекурсия

    Рекурсия – это вызов внутри тела некоторой функции самой себя.

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

    Function fact(n) { if (n === 1) { return 1; } return fact(n-1) * n; } console.log(fact(5)); // 120

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

    Что такое встроенные (стандартные) функции?

    В JavaScript имеется огромный набор встроенных (стандартных) функций. Данные функции уже описаны в самом движке браузера. Практически все они являются методами того или иного объекта.

    Например, для того чтобы вызвать встроенную функцию (метод) alert, её не надо предварительно объявлять. Она уже описана в браузере. Вызов метода alert осуществляется посредством указания имени, круглых скобок и аргумента внутри них. Данный метод предназначен для вывода сообщения на экран в форме диалогового окна. Текстовое сообщение берётся из значения параметра данной функции.

    // вызов функции alert alert("Некоторый текст"); JavaScript - Вызов функции alert



    Есть вопросы?

    Сообщить об опечатке

    Текст, который будет отправлен нашим редакторам: