Calling a function in javascript. Five ways to call a function

Functions

A function is a block of JavaScript code that is defined once and can be executed, or called, multiple times. You may already be familiar with the concept of a function under another name, such as a subroutine or procedure. Functions can have parameters: A function definition can include a list of identifiers, which are called parameters and act as local variables in the body of the function.

When calling functions, they can be passed values ​​or arguments corresponding to their parameters. Functions often use their arguments to calculate a return value, which is the value of the function call expression. In addition to the arguments, when any function is called, it is passed one more value that defines the context of the call - the value in the this keyword.

Functions in JavaScript are objects and can be used in different ways. For example, functions can be assigned to variables and passed to other functions. Because functions are objects, you can assign values ​​to their properties and even call their methods.

JavaScript allows function definitions to be nested within other functions, and such functions will have access to all variables present in the scope of the definition.

Defining Functions

A function definition begins with the function keyword, followed by the following components:

An identifier that specifies the name of the function

The name is a required part of the function declaration statement: it will be used to create a new variable to which the new function object will be assigned. In function definition expressions, the name may be absent: if present, the name will refer to the function object only in the body of the function itself.

A pair of parentheses around a list of zero or more identifiers, separated by commas

These identifiers will define the names of the function parameters and can be used as local variables in the function body.

A pair of curly braces with zero or more JavaScript instructions inside

These instructions make up the body of the function: they are executed every time the function is called.

The following example shows several function definitions in the form of statements and expressions. Note that function definitions as expressions are only useful if they are part of larger expressions, such as an assignment or function call, that do something with the newly declared function:

// Prints the names and values ​​of all properties of object obj function printprops(obj) ( for(var p in obj) console.log(p + ": " + obj[p] + "\n"); ) // Calculates the distance between points (x1,y1) and (x2,y2) function distance(x1, y1, x2, y2) ( var dx = x2 - x1; var dy = y2 - y1; return Math.sqrt(dx*dx + dy*dy ); ) // Recursive function (calling itself) that calculates the factorial function factorial(x) ( if (x

Note that in function definition expressions, the function name may not be present. The function declaration statement actually declares a variable and assigns it a function object.

A function definition expression, on the other hand, does not declare a variable. However, in definition expressions it is possible to specify the name of the function, as in the factorial function above, which may be required in the body of the function to call itself. If a function definition expression includes a name, that name will refer to a function object in the scope of that function. In effect, the function name becomes a local variable, accessible only in the function body. In most cases, the function name does not need to be specified in definition expressions, making definitions more compact.

Note that most (but not all) of the functions in the example contain a return statement. The return statement terminates the function and returns the value of its expression (if specified) to the calling program. If there is no expression in the return statement, it returns undefined. If there is no return statement in the function, the interpreter will simply execute all statements in the function body and return undefined to the calling program.

Most of the functions in the example evaluate to some value and use a return statement to return that value to the calling program. The printprops() function is slightly different in this sense: its job is to print the names of the properties of an object. It doesn't need to return any value, so there is no return statement in the function. The printprops() function will always return undefined. (Functions that do not have a return value are sometimes called procedures.)

Calling functions

The program code that forms the body of a function is executed not at the time the function is defined, but at the time it is called. Function calls are made using a call expression. A call expression consists of a function call expression that returns a function object, followed by parentheses with a comma-separated list of zero or more argument expressions inside.

If a function call expression is a property call expression - if the function is an object property or an array element (that is, a method) - then the call expression is a method call expression. The following snippet shows several examples of common function call expressions:

Printprops((x:4, age: 24)); var d = distance(1,1,5,6); var f = factorial(5) / factorial(12); f = square(5);

When a function is called, all argument expressions (specified between parentheses) are evaluated and the resulting values ​​are used as arguments to the function. These values ​​are assigned to parameters whose names are listed in the function definition. In the body of the function, parameter call expressions return the values ​​of the corresponding arguments.

When a normal function is called, the function's return value becomes the value of the calling expression. If a function returns after the interpreter has reached its end, undefined is returned. If a function returns as a result of a return statement, the value of the expression following the return statement is returned, or undefined if the return statement has no expression.

A method is nothing but a function that is stored as a property of an object. If you have a function func and an object obj, then you can define a method on obj called method as shown below:

// Define a simple object and function var obj = (); function func(a, b) ( return a+b;) // Add a method to object obj obj.method = func; // Now you can call this method var result = obj.method(4, 5);

Most often, when calling methods, you use the dot operator to access properties, but you can also use the square brackets form to access properties. For example, both of the following expressions are method call expressions:

Result = obj.method(4, 5); result = obj["method"](4, 5);

The arguments and return value of a method call are processed in exactly the same way as a normal function call. However, a method call has one important difference: the context of the call. A property access expression consists of two parts: an object (in this case obj) and the property name (method). In such method call expressions, obj becomes the calling context, and the function body is able to reference that object using the this keyword. For example:

Var obj = ( x: 0, y: 0, // Add method: function(a, b) ( this.x = a; this.y = b; ), // Another method sum: function() ( return this.x + this.y ) ); // Calling methods obj.add(15, 4); console.log(obj.sum()); // 19

Methods and the this keyword are central to the object-oriented programming paradigm. Any function used as a method actually receives an implicit argument - the object on which it was called. Typically, methods perform some operation on an object, and the method call syntax clearly reflects the fact that the function operates on the object.

Please note: this is a keyword, not a variable or property name. JavaScript syntax does not allow the this element to be assigned a value.

Function Arguments and Parameters

In JavaScript, function definitions do not specify parameter types, and function calls do not perform any type checking on the argument values ​​passed. In fact, JavaScript doesn't even check the number of arguments when calling functions. The subsections below describe what happens if the number of arguments in a function call is less than or greater than the number of declared parameters. They also demonstrate how you can explicitly check the types of a function's arguments if you need to ensure that the function is not called with invalid arguments.

Optional Arguments

When the number of arguments in a function call is less than the number of declared parameters, the missing arguments are set to undefined. It is often convenient to write functions so that some of the arguments are optional and can be omitted when calling the function. In this case, it is desirable to provide the ability to assign reasonably reasonable default values ​​to parameters that may be omitted. For example:

// Add enumerable names of // properties of object obj to array arr and return it. If the argument // arr was not passed, create and return a new array function getPropertyNames(obj, /* optional */ arr) ( if (arr === undefined) arr = ; // If the array is not defined, create a new for( var property in obj) arr.push(property); return arr; // This function can be called with 1 or 2 arguments: var a = getPropertyNames((x:1, y:1)); // Get the object's properties in a new array getPropertyNames((z:5),a); // add the properties of the new object to this array console.log(a); // ["x", "y", "z"]

Note that when declaring functions, optional arguments must complete the argument list in order to be omitted. The programmer who will write a call to your function will not be able to pass the second argument and at the same time omit the first: he will be forced to explicitly pass the value undefined in the first argument. Also note the /* optional */ comment in the function definition, which emphasizes the fact that the parameter is optional.

Variable length argument lists

If the number of arguments in a function call exceeds the number of parameter names, the function is unable to directly access unnamed values. The solution to this problem is provided by the Arguments object. In the function body, the arguments identifier refers to the Arguments object present in the call. The Arguments object is an array-like object that allows values ​​passed to a function to be retrieved by their numbers rather than their names.

Let's assume that a function func has been defined that requires one argument x. If you call this function with two arguments, the first one will be available inside the function by the name of the parameter x or as arguments. The second argument will only be available as arguments. Additionally, like real arrays, arguments has a length property that specifies the number of elements it contains. That is, in the body of a function called func with two arguments, arguments.length has the value 2.

The Arguments object can be used for a variety of purposes. The following example shows how to use it to check whether a function was called with the correct number of arguments, something JavaScript won't do for you:

Function func(x, y, z) ( // First checks to see if the correct number of arguments is passed if (arguments.length != 3) ( throw new Error("Func called with " + arguments.length + " arguments and required 3."); ) // And now the function code itself... )

Note that it is often not necessary to check the number of arguments, as in this example. The default behavior of the JavaScript interpreter is fine for most cases: missing arguments are replaced with the value undefined, and extra arguments are simply ignored.

The Arguments object illustrates an important feature of JavaScript functions: they can be written to take any number of arguments. The following function takes any number of arguments and returns the value of the largest one (the built-in Math.max() function behaves similarly):

Function maxNumber() ( var m = Number.NEGATIVE_INFINITY; // Loop through all arguments, find and // store the largest one for(var i = 0; i m) m = arguments[i]; // Return the largest value return m ; ) var largest = maxNumber(1, 10, 100, 2, 3, 1000, 4, 5, 10000, 6); // 10000

Functions like this that can take an arbitrary number of arguments are called variadic functions, variable arity functions, or varargs functions. This term arose with the advent of the C programming language.

Note that variadic functions must not be able to be called with an empty argument list. It makes perfect sense to use the arguments object when writing a function that expects a fixed number of required named arguments, followed by an arbitrary number of optional unnamed arguments.

Don't forget that arguments isn't actually an array - it's an Arguments object. Each Arguments object has numbered array elements and a length property, but is not technically an array. It's better to think of it as an object that has some numbered properties.

In addition to its array elements, the Arguments object defines the callee and caller properties. Trying to change the values ​​of these properties in ECMAScript 5 strict mode is guaranteed to throw a TypeError exception. However, in lax mode, the ECMAScript standard states that the callee property refers to the currently executing function. The caller property is not standard, but it is present in many implementations and refers to the function that called the current one.

The caller property can be used to access the call stack, and the callee property is especially useful for recursively calling unnamed functions:

Var factorial = function(x) ( if (x

Function Properties and Methods

We have seen that functions can be used as values ​​in JavaScript programs. The typeof operator returns the string "function" for functions, but functions are actually a special kind of object in JavaScript. And since functions are objects, they have properties and methods like any other objects. There is even a Function() constructor that creates new function objects. The following subsections describe the properties and methods of functions.

length property

In the function body, the arguments.length property specifies the number of arguments passed to the function. However, the length property of the function itself has a different meaning. This read-only property returns the number of arguments the function expects to receive - the number of declared parameters.

The following snippet defines a function called check() that receives an array of arguments from another function. It compares the arguments.length property (the number of arguments actually passed) with the arguments.callee.length property (the number of expected arguments) to determine whether the function has been passed as many arguments as it expects. If the values ​​do not match, an exception is thrown. The check() function is followed by a test function, func(), that demonstrates how to use the check() function:

// This function uses arguments.callee, so it // will not work in strict mode function check(args) ( var actual = args.length; // Actual number of arguments var expected = args.callee.length; // Expected number arguments if (actual !== expected) // If they do not match, an exception is thrown throw new Error("expected: " + expected + "; received " + actual ) function func(x, y, z) ( // Check number of expected and actually passed arguments check(arguments); // Now execute the rest of the function return x + y + z )

prototype property

Every function has a prototype property, which refers to an object known as the prototype object. Each function has its own prototype object. When a function is used as a constructor, the newly created object inherits the properties of that prototype object.

Prototypes and the prototype property were discussed in a previous article.

call() and apply() methods

The call() and apply() methods allow you to call a function indirectly, as if it were a method on some other object. The first argument to both call() and apply() methods is the object on which the function is called; this argument specifies the context of the call and becomes the value of the this keyword in the function body. To call func() (without arguments) as a method of obj, you can use any of the call() or apply() methods:

Func.call(obj); func.apply(obj);

Either way of calling it is equivalent to the following snippet (assuming obj doesn't have a property named m):

Obj.m = func; // Temporarily make func a method obj obj.m(); // Call it without arguments. deleteobj.m; // Remove temporary method.

In ECMAScript 5 strict mode, the first argument of the call() and apply() methods becomes the value of this, even if it is a simple value, null, or undefined. In ECMAScript 3 and in lax mode, the values ​​null and undefined are replaced by the global object, and the simple value is replaced by the corresponding wrapper object.

All other arguments to the call() method following the first argument specifying the calling context are passed to the called function. The apply() method acts like the call() method, except that the arguments to the function are passed as an array. If a function is capable of processing an arbitrary number of arguments, the apply() method can be used to call such a function in the context of an array of arbitrary length.

The following example demonstrates the practical use of the call() method:

// Below are two functions that display the properties and // property values ​​of an arbitrary object. Method // displays are passed as an argument func function print1(func, obj) ( for (n in obj) func(n +": " + obj[n]); ) function print2(func, objDevice, obj) ( for ( n in obj) func.call(objDevice, n +": " + obj[n] ) var obj = (x:5, y:10); print2(document.write, document, obj); // Works correctly print2(console.log, console, obj); print1(document.write, obj); // An Illegal invocation exception will occur because print1(console.log, obj); // it is impossible to call these methods without a context object

bind() method

The bind() method first appeared in ECMAScript 5, but is easy to imitate in ECMAScript 3. As its name suggests, the main purpose of the bind() method is to bind a function to an object. If you call func's bind() method and pass it an obj object, it will return a new function. Calling the new function (as a regular function) will call the original function func as a method on obj. Any arguments passed to the new function will be passed to the original function. For example:

// The function you want to bind function func(y) ( return this.x + y; ) var obj = (x:1); // Object to bind to var g = func.bind(obj); // Calling g(x) will call obj.func(x)

This type of binding is easy to implement in ECMAScript 3, as shown below:

// Returns a function that calls func as a method of object obj // and passes it all its arguments function bind(func, obj) ( if (func.bind) return func.bind(obj); // Use bind method if available else return function() ( // Otherwise bind as shown below return func.apply(obj, arguments); )

The bind() method in ECMAScript 5 does more than just bind a function to an object. It also performs partial casting: in addition to the this value, all arguments passed to the bind() method after its first argument will be bound. Partial application is a common technique in functional programming and is sometimes called currying.

Let's start with the fact that the JavaScript language supports the concept of OOP (object oriented programming). This concept is that there are such elements as objects and these objects have various properties and methods (functions) that allow you to manipulate them.

A function is a separate block of code that consists of one or more statements. It has its own (unique) name and can accept various parameters, depending on which it can perform a particular operation.

A method is also a function, but it already belongs to some class or object.

In order to call a method, you must first write the name of the object, then write the name of the method separated by a dot. The exception to this rule is when calling the alert(), confirm(), and prompt() methods of the window object. They can be called without specifying the object name. We have already become acquainted with these methods in this article.

Also, in previous articles we were introduced to the document.write() output method, which belongs to the document object.

So, in programming there is a very important opportunity, which is that you can create your own functions.

The function syntax looks like this:


As an example, let's create a simple function that will add the passed text to a paragraph and display it. And it will also make it bold and italic.

Function writeText(text)( //Add text in the paragraph and display it document.write("

"+text+"

"); ) //Call the created function writeText("Hello!");

Save the document and open it in the browser.


Comment! When declaring a function, curly braces must be present, no matter how many operators there are.

What are functions needed in programming?

The main advantage of using the function is the reduction in the size of the script source code.

Let's say we need to iterate over three one-dimensional arrays. As we know from this article: , the array is iterated using a loop. Without the function, the code for this script will look like this:

//declare three arrays var arr1 = ; var arr2 = ["b", 5, 9.2, "h", 8, 2]; var arr2 = ; for(var i = 0; i< arr1.length; i++){ document.write("

The array element arr1, with index " + i + " is equal to: "+ arr1[i] +"

"); ) for(var i = 0; i< arr2.length; i++){ document.write("

The array element arr2, with index " + i + " is equal to: "+ arr2[i] +"

"); ) for(var i = 0; i< arr3.length; i++){ document.write("

The array element arr3, with index " + i + " is equal to: "+ arr3[i] +"

"); }

So, in order not to write your own loop for each array, it is better to use a function in which we pass the array, and it will display all its elements on the screen. Thus, we, firstly, reduce the size of the code, and secondly, get rid of repeating code.

Function printArr(arr)( for(var i = 0; i< arr.length; i++){ document.write("

The array element with index " + i + " is equal to: "+ arr[i] +"

"); ) ) //declare three arrays var arr1 = ; var arr2 = ["b", 5, 9.2, "h", 8, 2]; var arr2 = ; //Call the created function to iterate through each array printArr (arr1); printArr(arr2); printArr(arr3);

Function parameters

A function can take any number of parameters, from one to infinity. Or, it can be completely without parameters.

Let's create a parameterless function that will simply print the classic "Hello world" phrase to the screen.

Function helloWorld())( document.write("Hello World"); ) //Call the function without parameters, helloWorld helloWorld();

Any function parameter can have its own default value. This means that if we do not pass any value to this parameter when calling the function, it will use its default value.

For example, let's create a function that adds two passed numbers. If we pass only one number, then, by default, the second number will be 4.

Function summa(number1, number2 = 4)( document.write("

The sum of the numbers " + number1 + "(First parameter) and " + number2 + "(Second parameter) is equal to: " + (number1 + number2) + "

"); ) //Call a function that, by default, will output the result of adding the passed number, with the number 4. summa(5); // Result: 9 //If we also supply the second parameter, the function will output the result of adding the numbers from both parameters .summa(5, 20); // Result: 25

It is also possible that inside a function one could call another existing function.

For example, let's call the first function we created, writeText(), inside the previous summa() function. We will pass the result of adding numbers to the writeText() function. In this case, the code for the summa() function will look like this:

Function summa(number1, number2 = 4)( writeText(number1 + number2); ) //Call the function summa summa(5); // Result: 9 summa(5, 20); // Result: 25

Functions that return some value

So far we have written functions that display the result on the screen immediately.

Now let's learn how to write a function that returns some result. We can add this result to some variable and work with it further.

In order to better understand what we are talking about, let’s remember methods such as prompt() and confirm(). These methods actually return the value received from the user, rather than displaying it.

For example, let's create our own function that will return the last element of the array passed as a parameter.

Function lastElement(arr)( //Return the last element of the passed array return arr; ) //Declare the array var otherArr = ["iphone", "asus", 2000, 9.8, "twix"]; //Call the created lastElement function and pass it the created array as a parameter otherArr var lastEl = lastElement(otherArr); //Display the resulting last element of the array alert(lastEl);

As a result, we will get the word 'twix', since this word is the last element of the otherArr array.

The alert() method does not return anything. That is, if we try to display a variable whose type contains the result of calling the alert() method, we will see the value undefined . This is the same as trying to display the value of an empty variable.

For example, let's take the result of the last call to alert() from the previous example, put it in the resAlert variable and use the writeText function we created to try to print the result.

//Display the received last element of the array var resAlert = alert(lastEl); var test; writeText(resAlert); //undefined writeText(test); //undefined

As you can see, in both cases we received the value undefined.

Global and local variables

Global variables are those variables that are declared outside the function. That is, all those variables that are not declared inside the function itself are global. They are visible (valid) throughout the document.

Local variables are those variables that are declared within the function itself. And they are only valid within a given function. Outside of it, local variables will no longer work.

Local and global variables are not related to each other in any way.


In the example from the image, if we tried to print the contents of variable x, we would get an undefined message because we forgot to call the other() function.

Therefore, in order for the changes made inside the function to work, it is necessary to call this function.

We call the other() function, and if we now try to display the value of the variable x, we will see the number 4 as a result.

To access a global variable from inside a function, you don’t need to do anything, you just need to use it. Changes made to global variables will be visible outside the function.

Var x = 8; function increment() ( x++; ) //Call the function increment() increment(); alert(x); //Result: 9

If we do not want the global variable to change, we must declare a local variable (possibly with the same name as the global one) and all actions will be performed on it.

Var g = 100; function func())( var g = 14; g *= 2; // This is the same as g = g * 2 alert(g); // Result: 28 ) // Call the function. func(); alert(g);//Result: 100

That's all, dear readers, now you know what a function is, how to create your own function, how to call a function and what types of functions exist. You also learned what global and local variables are.

As I wrote at the beginning of the article, functions are very important elements, so you should know them perfectly.

Tasks
  • Create a function that takes two numbers as parameters and returns the result of multiplying those numbers.
  • Print the result.
  • May 24, 2011 at 01:13 Five ways to call a function
    • JavaScript
    • Translation

    I often come across JavaScript code where errors are caused by a misunderstanding of how functions work in JavaScript (by the way, much of this code was written by me). JavaScript is a multi-paradigm language, and it has functional programming mechanisms. It's time to explore these possibilities. In this article, I will tell you five ways to call functions in JavaScript.

    In the early stages of learning JavaScript, beginners usually think that functions in it work in much the same way as in, say, C#. But the mechanisms for calling functions in JavaScript have a number of important differences, and ignorance of them can result in errors that will not be easy to find.

    Let's write a simple function that returns an array of three elements - the current this value and the two arguments passed to the function.
    function makeArray(arg1, arg2)( return [ this, arg1, arg2 ]; )

    The most common way: global call Beginners often declare functions as shown in the example above. Calling this function is easy:
    makeArray("one", "two"); // => [ window, "one", "two" ]
    Wait. Where does the window object come from? Why is this equal to window?

    In JavaScript, no matter whether the script is executed in the browser or in another environment, it is always defined global object. Any code in our script that is not "bound" to anything (that is, outside of the object declaration) is actually in the context of the global object. In our case, makeArray is not just a function “walking” on its own. In fact, makeArray is a method of the global object (in the case of code execution in the browser) window . It's easy to prove:
    alert(typeof window.methodThatDoesntExist); // => undefined alert(typeof window.makeArray); // => function
    That is, calling makeArray("one", "two"); is equivalent to calling window.makeArray("one", "two"); .

    It saddens me that this is the most common way of calling functions, because it implies the presence of a global function. And we all know that global functions and variables are not the best form in programming. This is especially true for JavaScript. Avoid global definitions, and you won't regret it.

    Function calling rule #1: If a function is called directly, without specifying an object (for example, myFunction()), the value of this will be the global object (window if the code is executed in the browser).

    Calling a Method Let's create a simple object and make makeArray its method. Let's declare the object using literal notation, and then call our method:
    // create an object var arrayMaker = ( someProperty: "some value", make: makeArray ); // call the make() method arrayMaker.make("one", "two"); // => [ arrayMaker, "one", "two" ] // alternative syntax, use square brackets arrayMaker["make"]("one", "two"); // => [ arrayMaker, "one", "two" ]
    Do you see the difference? The value of this in this case is the object itself. Why not window , as in the previous case, since the function declaration has not changed? The secret is how functions are passed in JavaScript. Function is a standard JavaScript type that is actually an object, and like any other object, functions can be passed around and copied. In this case, we've essentially copied the entire function, including the argument list and body, and assigned the resulting object to the arrayMaker object's make property. This is equivalent to a declaration like this:
    var arrayMaker = ( someProperty: "Some value"; make: function (arg1, arg2) ( return [ this, arg1, arg2]; ) );
    Function Calling Rule #2: In a function called using method call syntax, such as obj.myFunction() or obj["myFunction"]() , this will have the value obj .

    Misunderstanding of this generally simple principle often leads to errors when processing events:
    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(); );
    Clicking the first button will show a message "btn1" because in this case we are calling a function as a method, and this inside the function will get the value of the object that this method belongs to. Clicking the second button will give "window" because in this case we are calling buttonClicked directly (i.e. not like obj.buttonClicked()). The same thing happens when we assign an event handler to the element tag, as in the case of the third button. Clicking the third button will show the same message as the second.

    When using libraries like jQuery, you don't need to think about this. jQuery will take care to rewrite the this value in the event handler so that the this value is the element that raised the event:
    // use jQuery $("#btn1").click(function() ( alert(this.id); // jQuery will make sure "this" is a button ));
    How does jQuery manage to change the value of this ? Read below.

    Two more ways: apply() and call() It is logical that the more often you use functions, the more often you have to pass them and call them in different contexts. Often there is a need to override the value of this . If you remember, functions in JavaScript are objects. In practice, this means that functions have predefined methods. apply() and call() are two of them. They allow you to override the this value:
    var car = ( year: 2008, model: "Dodge Bailout" ); makeArray.apply(car, [ "one", "two" ]); // => [ car, "one", "two" ] makeArray.call(car, "one", "two"); // => [ car, "one", "two" ]
    These two methods are very similar. The first parameter overrides this . The differences between them are in the subsequent arguments: Function.apply() accepts an array of values ​​that will be passed to the function, while Function.call() accepts the arguments separately. In practice, in my opinion, it is more convenient to use apply() .

    Function Calling Rule #3: If you want to override the value of this without copying the function to another object, you can use myFunction.apply(obj) or myFunction.call(obj) .

    Constructors I won't go into detail about declaring custom types in JavaScript, but I think it's necessary to remind you that there are no classes in JavaScript, and any custom type needs a constructor. In addition, it is better to declare methods of a custom type using prototype , which is a property of the constructor function. Let's create our own type:
    // declare the constructor function ArrayMaker(arg1, arg2) ( this.someProperty = "no matter"; this.theArray = [ this, arg1, arg2 ]; ) // declare methods ArrayMaker.prototype = ( someMethod: function () ( alert( "Called by someMethod"); getArray: function () ( return this.theArray; ) ); var am = new ArrayMaker("one", "two"); var other = new ArrayMaker("first", "second"); am.getArray(); // => [ am, "one", "two" ]
    The important thing in this example is the presence of the new operator before the function call. If it weren't for it, it would be a global call, and the properties created in the constructor would belong to the global object. We don't need that. Additionally, constructors usually do not return values ​​explicitly. Without the new operator the constructor would return undefined , with it it returns this . It is considered good style to name constructors with a capital letter; This will remind you of the need for the new operator.

    Otherwise, the code inside the constructor will likely be similar to code you would write in another language. The value of this in this case is the new object you are creating.

    Function Calling Rule #4: When calling a function with the new operator, the value of this will be a new object created by the JavaScript runtime. If this function does not return any object explicitly, this will be returned implicitly.

    Conclusion Hopefully, understanding the difference between different ways of calling functions will help you improve your JavaScript code. Sometimes errors related to the this value are difficult to catch, so it makes sense to prevent them in advance.

    JavaScript functions allow you to organize scripts and make code reuse easy. Instead of creating long pieces of code scattered throughout an HTML page, scripts are organized into logical groups.

    Declaring and Calling a JavaScript Function

    The JavaScript function syntax is as follows:

    function ""name"" (""argument1"", ""argument2"", ""argument3"" ...) ( ""operators"" return ""value"" )

    The name determines what we will call the function when we call it. The arguments specify the values ​​that are passed to the function for processing. The statements section represents the body of the function that performs the processing. The optional return statement allows you to return a value.

    The following example shows a function defined in the section of an HTML page and called in the section:

    function sayHello() ( alert("Hello!"); ) sayHello();

    Passing Arguments to a Function

    In the example above (script type text JavaScript function), no arguments are passed to the function. Typically a function is designed to perform some action with several arguments:

    A simple example of a JavaScript function function sayHello(day, month) ( alert("Hello! Today is " + day + " " + month); ) sayHello("24", "July"); sayHello("1", "August"); sayHello("24", "May");

    In this example, the JavaScript callback function is called multiple times, taking arguments that are then used to create a string that is displayed in the dialog box. To do this without the function, you would have to repeat the script in the section three times. Obviously, using a function is a more efficient approach.

    Returning a value from a function

    The return statement is used to return a value from a function and use it at the place where the function is called. As an example, we will declare a function that adds two arguments and returns the result:

    A simple JavaScript function example var result = addValues(10, 20) document.write("Result = " + result);

    In the example above, we are passing the values ​​10 and 20 to the addValues ​​function. The addValues ​​function adds these two values ​​and returns the result. The return statement assigns the result to the result variable, which is then used to create a string that is printed on the HTML page.

    A JavaScript function call can be made in different places. For example, it is not necessary to assign the result as the value of a variable. You can use it directly as an argument when calling document.write .

    It's important to note that a function can only return one value:

    A simple example of a JavaScript function function addValues(value1, value2) ( return value1 + value2; ) document.write("Result = " + addValues(10, 20)); JavaScript onclick functions can also be used in conditional statements. For example: A simple example of a JavaScript function function addValues(value1, value2) ( return value1 + value2; ) if (addValues(10, 20) > 20) ( document.write("Result > 20"); ) else ( document.write ( "Result< 20"); }

    Where to place function declarations

    There are two places it's recommended to place JavaScript function return declarations: inside a section of the HTML document or in an external .js file. The second option is considered the most preferred location, as it provides the greatest flexibility.

    The goal of creating functions is to make them as general as possible in order to maximize reusability.

    The translation of the article “Understanding JavaScript Functions” was prepared by the friendly project team.

    Good bad

    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 scope 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 has proven 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);

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