Four patterns of function calls in JavaScript

Original author: Barry Steyn
  • Transfer
JavaScript was introduced as a functional programming language. The reason is that functions in JS do not just divide the logic into operating blocks, functions are first-class objects that can create other objects. Such dependence on functions is both a strength and a real curse of this language. The strong point is that the language, possessing similar features, becomes lightweight and fast (as JavaScript creators initially saw it). However, if you do not know what you are doing, definitely expect trouble.

I suggest looking at the patterns of calling functions, and more precisely at how the result changes significantly depending on the selected pattern. We will also consider how it behaves.this, depending on how the function is called.

So there are four ways to call functions:

  • Method Invocation - Method Invocation
  • Function Invocation - Function Invocation
  • Constructor Invocation - Constructor Invocation
  • Call apply and call - Apply And Call Invocation


Function execution


JavaScript, like all modern languages, can modulate the logic inside functions, and these functions can be called at any time, in the middle of an already running process. By calling the function, we pass it the necessary parameters and process control, stopping the current operation. The call operator is parentheses () , which can enclose parameters separated by commas.

Unfortunately, there are several patterns for calling functions. You do not need to be aware of them. They need to be memorized and understood, because, depending on the selected pattern, you will get different results. In my opinion, this feature is a mistake in the design of the language, and if JavaScript was created in a hurry and at a b aWith the utmost attention, various problems of a similar nature could be avoided.

Four patterns


As already mentioned, the operator for calling the function is one, and there are four ways to call it.

Method Invocation - Method Invocation

When a function is part of an object, it is called a method. A “method call” is a call to a function belonging to an object. Example:

var obj = {
    value: 0,
    increment: function () {
        this.value + = 1;
    }
};
 
obj.increment (); 

In the “method call”, the value thiswill refer to the object to which the function belongs, in our case, to obj, and this connection will be established after the function is launched, which carries the term “ late binding ”.

Function Invocation - Function Invocation

The function call is performed using the operator ():

add (2,3); //5

Using this pattern, it is thisattached to the global object. This is undoubtedly a mistake of the language - a constant binding of this to a global object can destroy its context. This is especially noticeable if you use the function inside the method. Let's look at an example:

var value = 500; // Global variable
var obj = {
    value: 0,
    increment: function () {
        this.value ++;
 
        var innerFunction = function () {
            alert (this.value);
        }
 
        innerFunction (); // Function invocation pattern
    }
}
obj.increment (); // Method invocation pattern
 

What do you think will be displayed on the screen? If you decide that 1 - you're wrong (but don't blame yourself - blame the crooked JavaScript design). The correct answer is 500. Note that it innerFunctionis called using the aforementioned “function call” pattern, and is thisbound to the global object accordingly . As a result, we get 500.

You can easily get around this problem by creating a variable this, but in my opinion this is a hack.

var value = 500; // Global variable
var obj = {
    value: 0,
    increment: function () {
        var that = this;
        that.value ++;
 
        var innerFunction = function () {
            alert (that.value);
        }
 
        innerFunction (); // Function invocation pattern
    }
}
obj.increment ();

Thus, we bound thisto the object inside which the function is called.

Constructor Invocation - Constructor Invocation

Warning: this is another JavaScript feature that is very different from the classic OOP languages! This is a prototype-oriented programming language, but its creators thought that the people of the "classical school" (of which most) would feel uncomfortable. As a result, the principles of classical OOP were added to prototype JavaScript and it turned out what happened - a mess.

In classic OOP, an object is an implementation of a class. In C ++ and Java, an operator is used for such an implementation new. Apparently, the creators of JS decided not to go far for an example, and implement something similar in the “constructor call”

pattern ... The pattern is started by placing the statement newright before the call, for example:

var Cheese = function (type) {
    cheeseType = type;
    return cheeseType;
}
 
cheddar = new Cheese ("cheddar"); // Returns an object, not a type

Despite the fact that it Cheeseis a functional object (which means it can digest code), we created a new object by calling function c new. thisin this case, it will refer to the newly created object, and the behavior returnwill be changed. Speaking of return. Its use in the "constructor call" has two features:

  • if the function returns a number, a chain, a logical expression (true / false), null or undefined, returnit will not work, and we will getthis
  • if the function returns the implementation of the object (that is, everything except simple variables), we will see this object, not this

var obj = {
    data: "Hello World"
}
 
var Func1 = function () {
    return obj;
}
 
var Func2 = function () {
    return "I am a simple type";
}
 
var f1 = new Func1 (); // f1 is assigned to the object
var f2 = new Func2 (); // f2 is assigned to the new object

We could ignore the use this, and assign literals to objects, if not for one thing: the creators of JavaScript associated with this pattern one of the key features of the language - creating objects with an arbitrary reference to the prototype ( more details here - Eng. ). This pattern is not intuitive, moreover, problems often arise with it. Douglas Crockford proposed a solution to the problem: you can use augment object with the create method. I am pleased to report that, starting with version 1.8.5, JavaScript Object.createis a fully working tool.

Call apply and call - Apply And Call Invocation

This pattern is thought out much better than others. It allows you to manually start the function, at the same time providing it with parameters and indicating this. Due to the fact that our functions are full-fledged objects, every function in JavaScript is associated with Function.prototype , which means we can easily add methods to them.

This pattern uses two parameters: the first is the object to bind to this, the second is the array associated with the parameters:

var add = function (num1, num2) {
        return num1 + num2;
}
 
array = [3,4];
add.apply (null, array); // 7

The example above thisrefers to null(the function is not an object), and the array is bound to num1and num2. But let's continue to experiment with the first parameter:

var obj = {
    data: 'Hello World'
}
 
var displayData = function () {
    alert (this.data);
}
 
displayData (); // undefined
displayData.apply (obj); // Hello World
 

This example uses applyto bind thisto obj. As a result, we are able to get value this.data. The real value of apply is precisely binding this.

In JavaScript, there is also an operator callthat is similar to applyeverything except that it receives not parameters, but a list of arguments.

Conclusion


For better or worse, JavaScript is about to take over the world. Therefore, it is simply necessary to know about its features, especially those that should be avoided. Understanding the four function call patterns is a must for JavaScript learners. Hope this post helps you.

Also popular now: