JS functions - understanding function calls

As front-end programmers, we have all written JS functions and called JS functions, but have you ever thought about what really happens when a function is called? In fact, the way the function is called has a great impact on the execution of the code within the function, mainly reflected in how the this parameter and the function context are established, which is very important.

Then the first question comes:

Do you know there are several ways to call a function in JS? ( Don’t rush to look back, you can think about it in your mind first )

The answer is: 4 types ;

they are, respectively:

  • As a function - eat(), is called directly.
  • As a method - dog.eat(), it is associated with an object and implements object-oriented programming.
  • As a constructor - new Dog(), instantiates a new object.
  • Through the function's apply or call method - eat.apply(dog) or eat.call(dog).

Let’s look at them one by one:

1. Called directly as a function

It sounds a bit silly (of course a function must be called as a function, otherwise how can it be called?), haha, it seems a bit like a tongue twister. However, what we say here is called "as a function" to distinguish it from the other three calling methods. Generally speaking, when a function is called through the () operator and the executed function expression does not exist as an attribute of an object , it is called directly. In human terms, as long as it is not called as a method, constructor, or through apply and call, it is a proper direct call.

Among them, there are three types of function calls:

When called in this way, there are two possibilities for the function context (the value of the this keyword):
non-strict mode: global context (window object);
strict mode: undefined;

2. Called as a method

When a function is assigned to a property of an object and the function is called via a reference to the object's property, the function is called as a method of the object.

In this case, the function is called a method, and the object called is called the context of the function, and can be accessed through this inside the function. This is also one of the main ways that JS implements object-oriented programming.

So what are the similarities and differences between when a function is called as a normal function and when it is called as a method?

In the above code, we created an independent ordinary function whatsMyContext, and all the code after it refers to and calls this function.

It can be seen that in calls 1 and 2, even if we create a variable to reference the original function, when calling the function with this variable, the printed this value is still the window object, because this variable is also declared in the global environment of.
Then, in calls 3 and 4, we create two objects, both of which contain a property called getMyThis whose value is a reference to the function whatsMyContext. In this way, we create a method named getMyThis on the object. However, don't think that whatsMyContext has become a method of obj_1 or obj_2. No, it is still an independent function, it just can be called in multiple ways. When calls 3 and 4 are executed, you can see that obj_1 and obj_2 are printed out respectively. This just confirms what we said earlier. When a function is called as a method of an object, its context will be the calling object and can be accessed through the parameter (this) inside the function .

3. Called as a constructor

When a function is used as a constructor, there is no essential difference in declaration from other functions. Both function declarations and function expressions can be used. The core difference is in the calling method. The constructor uses the new keyword.

If the function in our previous code is called as a constructor, the code is as follows:

But in practice, such a constructor is not particularly useful to us. why? This will be explained next.

Calling a function as a constructor is a powerful feature in JS. The following code is a practical example:

In this example, we created a function named Dog as the constructor. When called via the new keyword, it creates an empty object instance and passes it to the function as its context (the this parameter). In the constructor, a property named bark is created on the object and assigned to a function, making the function a method of the newly created object.

Generally speaking, when calling a function using the keyword new, the following actions will be triggered:

  1. Create a new object.
  2. This object is passed to the constructor as the this parameter, thereby becoming the function context of the constructor.
  3. The newly constructed object is used as the return value of the new operator (except when the function returns object). (The situation mentioned here involves the return value of the constructor. If you are interested, you can search it yourself. I will not expand it this time)

The above explains why whatsMyContext we mentioned above is not suitable as a constructor. The purpose of the constructor is to create a new object, initialize it, and then use it as the return value of the constructor. Anything that goes against these two points is not suitable as a constructor.

4. Use the apply and call methods to call

By now, you should have noticed that the main difference between the different types of function calls is the object that is ultimately passed to the executing function as the function context (this).

If you are smart and studious, you may ask: What if I want to explicitly specify the context when a function is called? Good question, now you need to apply and call.

apply and call exist on every function. They are methods provided by JS that can be used to explicitly specify any object as the context of the function.

(Yes, you read that right, functions also have methods. After all, we (functions) exist as first-class objects in JS. They are created by the built-in Function constructor. Of course, they have the same functions as ordinary objects. properties and methods.)

The usage methods of apply and call are similar. The only difference is that the form of passing parameters is different, as follows:

apply and call are usually used to solve problems caused by incorrectly pointing the default bound context (this) in some callback functions. Their functions are similar, they are both used to change the point of this, but the form of passing parameters is different. call needs to pass the actual parameters according to the number of formal parameters (the parameters are written one by one), and apply needs to pass an array, so When using it, just stick to one principle: choose any method that can simplify the code. In summary, choose a method that matches the existing parameters. If there is an unrelated set of values, use the call method directly. If the existing parameters are of array type, the apply method will be better. 

Extensions - Two other options for resolving function context:

In addition to the function context that can be known through the above calling methods, there are two other options:

  1. Arrow functions - bypassing function context:

    In addition to allowing us to create functions more concisely and elegantly, arrow functions also have an even better feature when used as a callback function: an arrow function does not have a separate this value; its this is the same as the context in which it is declared. Of course, this feature will also lead to some seemingly strange behaviors, which require detailed analysis of the specific situation.
  2. bind - bind function context

    In addition to using apply and call to directly specify the context to call the function, the function can also use the bind method to create a new function with a specified context. When a new function is created, no matter which method is used to call it, this is set to the bound object itself . At the same time, it should be noted that using the bind method does not modify the original function, but creates and returns a brand new function.

Summarize

  • There are 4 ways to call functions:
    1. Called as a function: eat()
    2. Called as a method: dog.eat()
    3. Called as constructor: new Dog()
    4. Called through the apply and call methods: eat.apply(dog) or eat.call(dog)
  • The way the function is called affects the value of this:
    1. Called as a function:
      1. Non-strict mode: window
      2. Strict mode: undefined
    2. Called as a method: this points to the calling object
    3. Called as a constructor: this points to the newly created object
    4. Called by apply or call: this points to the first parameter of apply or call
  • Arrow functions do not have a separate this value. This is determined when the arrow function is created.
  • All functions can use the bind method to create a new function and bind it to the parameters passed in the bind method. The bound function has the same behavior as the original function.

Guess you like

Origin blog.csdn.net/weixin_46422035/article/details/125423051