How JavaScript functions are called and how arguments are passed

Understanding how functions are called helps you learn and analyze JavaScript code in depth.

In JavaScript, functions are first-class citizens. Functions are data types in JavaScript, not just modules like in C# or other descriptive languages. There are four invocation modes for functions: function invocation, method invocation, constructor invocation, and apply and call invocation. The main difference in all of these patterns is the meaning of the this keyword, which is described below. (Note that the following code is running in a browser environment.)

  1. Analyze the four call forms of a function
  2. Figure out what this means in the function
  3. The process of specifying a constructor object
  4. Learn to use context to call functions

First, function call form

The function call form is the most common and best understood form. The so-called functional form is the general declaration of the function directly after the immediate call. Such as:

function foo(){
    console.log(this);
}
foo();//Window
Copy the code

The function call pattern, the function name (parameter), can’t add anything else to it, like the object o.fin (). In function call mode, this represents the global object Window. Any self-calling function is a function pattern.

Method invocation pattern

The function call pattern is very simple and is the most basic way to call. But the same thing happens when you assign a function to a member of an object. When a function is assigned to a member of an object, it is no longer called a function, but a method. A method call is a method call of an object. What is a method? A method is a function in itself, but a method is not a stand-alone function. Instead, it is invoked through an object boot. That is, a method object must have a host object. Object. Method (parameter). This represents the bootstrap method object, which is the host object. Compare function call patterns:

  1. The method call pattern is not independent and requires a host, whereas the function call pattern is independent;
  2. Method call mode mode: obj.fun(); Function call mode mode: fun();
  3. In the method invocation pattern, this refers to the host; In function call mode this refers to the global object Window.
// Define a function
function foo(){
    console.log(this);
}
// Assign it to an object
var o = {};
o.fn = foo;// Note that there are no parentheses here
/ / call
o.fn();//o
Copy the code

In function calls, this refers to the global object Window, while in methods this refers to the current object, that is, this in O.fin refers to object O. Meituan an interview question:

var length = 10;
function fn(){
    console.log(this.length);
}
var obj = {
    length:5.method:function(fn){
        fn();//10 No bootstrap object, function call mode
        arguments[0] ();/ / 2
        //arguments is a pseudo-array object, where a call is equivalent to a call from an array index
        // This refers to the pseudo-array, so this.length is 2}}; obj.method(fn,1);// Prints 10 and 2
obj.method(fn,1.2.3);// Prints 10 and 4
Copy the code

Resolution:

  1. Fn () has no boot object in front of it and is in function call mode. This is a global object and outputs 10.
  2. Arguments0, ArgumentArguments is a pseudo-array object, where the call is equivalent to being called through an array index. Arguments. length = 2; this = arguments.length = 2;

Here the bootstrap object (host) is the Arguments object.

Constructor invocation pattern

Also function, in pure function mode, this denotes window; In object method mode, the value of this is the current object. In addition to these two cases, functions in JavaScript can also be constructors. The syntax for using a function as a constructor is to prefix the function call with the new keyword. Such as:

// Define a constructor
var Person = function(){
    this.name = 'Programmer';
    this.sayHello = function(){
        console.log('Hello');
    };
};
// Call the constructor to create the object
var p = new Person();
// Use objects
p.sayHello();//Hello
Copy the code

The above example first creates a constructor, Person, and then uses the constructor to create the object P. The new syntax is used here. The sayHello() method is then called using the object. As you can see from the example, this refers to the object itself. In addition, there are several variations of the function as a constructor:

  1. All attributes that need to be used by objects must be guided by this;
  2. The function’s return statement has been rewritten to return this if it returns a non-object.

If I execute the following code in sequence, what will be the output

function Foo(){
    getName = function(){
        console.log(1);
    }
    return this;
}
Foo.getName = function(){
    console.log(2);
}
Foo.prototype.getName = function(){
    console.log(3);
}
var getName = function(){
    console.log(4);
}
function getName(){
    console.log(5);
}

Foo.getName();2 / / output.
// Call Foo as the object's dynamically added property method getName
//Foo.getName = function(){console.log(2); }

getName();/ / output 4.
// Foo has not been executed and getName has not been overridden
GetName =function(){console.log(4); }

Foo().getName();/ / output 1
//Foo() executes, overwriting the global getName and returning this
//this is window, Foo().getName() is window.getname
Function (){console.log(1); function(){console.log(1); }
// The output is 1
Function (){console.log(1); function(){console.log(1); }

getName();/ / output 1
/ / the window. The getName (), output 1

new Foo.getName();2 / / output
Foo().getName(); // Foo().getName();
// so foo.getName is a whole, equivalent to new (foo.getName)();
// Foo. GetName is function(){console.log(2); } a reference
// Then new (foo.getName)() instantiates the object with foo.getName as its constructor.
// Just like new Person(); Person is a constructor


new Foo().getName();3 / / output
// find the constructor (), equivalent to (new Foo()).getName();
// Execute new Foo() => instantiate an object with Foo as the constructor
//(new Foo() ).getName; Access the getName property of the instantiated object
// The instance object does not have a getName attribute, nor was it added when constructing. If you cannot find it, look for it in the prototype
// find foo.prototype.getName = fucntion(){console.log(3); }
(new Foo()).getName() = 3

new new Foo().getName();// The output is 3
New ((new Foo()).getName) ()
(new Foo()).getName
//new Foo() instantiates the object with Foo as its constructor
//new Foo().getName = getName; //new Foo().getName = getName
// find foo.prototype.getName = function() {console.log(3); }
// So the inner layer (new Foo()).getName is a stereotype property of the object instantiated from Foo
// The attribute value is a function function(){console.log(3); } a reference
// So outer new ((new Foo()).getName)() in function(){console.log(3); } is the constructor that constructs the instance
// Console. log(3) is executed during construction, and output 3

Copy the code

This in the constructor

Analyze the process of creating an object and understand the meaning of this.

var Person = function(){
    this.name = 'Programmer';
};
var p = new Person(); 
Copy the code

Here we define the function Person first. Let’s examine the execution:

  1. The program does not execute the function body at this point, so the JavaScript interpreter does not know the contents of the function.
  2. The new keyword is then executed to create the object, the interpreter clears memory, gets a reference to the object, and passes the reference to the new object to the function.
  3. The function is then executed, passing the object reference to this. That is, in the constructor, this is the object just created by new.
  4. Then add a member to this, which is to add a member to the object.
  5. Finally, the function ends, returns this, and passes this to the variable on the left.

After analyzing the execution of the constructor, we can see that this in the constructor is the current object.

Return in the constructor

In the constructor, the meaning of return changes. First, if the constructor returns an object, the original meaning is retained. Return this if the object is not inverted, such as a number, a Boolean, and a string, or this if there is no return statement, for example:

// Return an object
var foo = function(){
    this.name = 'Joe';
    return {
        name:'bill'
    };
};
// Create an object
var p = new foo();
// Access the name attribute
console.log(p.name);/ / li si
Copy the code

Execute the code, and the output here is “Li Si”. The constructor returns an object and returns the object after it.

// Define a constructor that returns non-object data
var foo = fucntion() {
    this.name = 'Joe';
    return 'bill';
}
// Create an object
var p = new foo();
console.log(p.name);/ / zhang SAN
Copy the code

Execute the code, and the output is “triple”, because the return is a string, which is a primitive type, so the return statement is invalid, return this object.

4. Context invocation mode

Environment call mode => Different call mode in different environments is simply a unified format, you can achieve function mode and method mode syntax

  • Call form, function name. Call (…)
  • The apply form, function name. Apply (…)

These two forms function exactly the same, the only difference being the form of the parameters. Learn the apply form first, and then look at the call form

Apply method call form

The purpose of existential context calls is to allow method borrowing without contaminating objects.

  • If you want the function to be called as a function, you can use foo.apply(null); // The context is window

  • If you want it to be a method call pattern, note that you need to provide a host object foo.apply(obj); // The context is the obj object passed in

function foo(num1,num2){
    console.log(this);
    return num1+num2;
}
// Function call mode
var res1 = foo(123.567);
// method call
var o = { name: 'chenshsh' };
o.func = foo;
var res2 = o.func(123.567);
Copy the code

Call with apply if the function is parameterized. The first argument to apply is either null or an object.

  1. If null, it’s a function call
  2. If it’s an object, it’s a method call, and that object is the host object, followed by an array of arguments that place all of the function’s arguments in the array
// Function mode
foo(123.567);
foo.apply(null[123.567]);// Apply with the window context

// Method pattern
o.func(123.567);
var o = { name:'chenshsh' };
foo.apply(o,[123.567]);// Apply with o as context
Copy the code

Call method call

When called with Apply, function arguments must be in the form of arrays. But sometimes array wrapping is complicated, so call is introduced, which is exactly the same as Apply except that the parameters do not use arrays.

foo(123.456);
foo.apply(null[123.456]);
foo.call(null.123.456);
Copy the code
  1. Call (null, argument 1, argument 2, argument 3…) ;
  2. Call (obj, parameter 1, parameter 2, parameter 3…) ;

When no arguments are passed, apply is exactly the same as call