JS function call and “this” processing. All are based on the original text processing, the other are direct translation may be a little stiff, so for the convenience of the text, made some simple localization processing. If you want to learn directly from the text, you can ignore this article.

There has been a lot of confusion about how JS functions are called for years, especially in the case of the syntax mechanism for this.

In my opinion, understanding how the core functions are called, and also verifying how some of the other implementations based on the core functions work, solves the problem mentioned above.

The Core Primitive

First, let’s take a look at some of the highlights of the core Function call mechanism – the call method of the Function object. The call function is called as follows:

  1. willparametersThe second value to the last one is stripped out and rebuilt with a new oneThe list of parameters(argList)
  2. The first value of the passed function is assigned tothisValue
  3. Calling the function, in the process, willthisValueAssigned tothis.argListArgument list as a function

The following is an example:

function hello(thing){
    console.log(this+ "says hello"+ thing);
}

hello.call("The North is the south."."world");
// Output result: says hello world

Copy the code

As it turns out, when we call hello(), we assign the value of this to north and world to the list of arguments to the Hello runtime. The above processing flow is the core mechanism of JS function calls. You can roughly think of other function call mechanisms as encapsulation/simplification of the core mechanism (desugar).

Simple Function Invocation

Obviously, calling a function using call doesn’t seem like a very clever subchild. So, JS runs use the simple syntax Hello (“world”) to call the function directly.

function hello(thing){
    console.log("Hello" + thing);
}

// Simplified syntax (encapsulated syntax)
hello("world")
// Core syntax
hello.call(window."world");
Copy the code

NOTE: This is slightly different in ECMAScript 5’s strict mode:

// Simplify the syntax
hello("world");
// Core syntax
hello(undefined."world");
Copy the code

To sum up: the simple function fn(… Call (window [es5-strict :undefined],… The args).

NOTE

(funciton(){}) () ==>(function(){}).call(window [es5-strict :undefined])

Member Functions

In js application scenarios, functions as object attributes are also very common scenarios. In this scenario, the following simplification occurs:

var person ={
    name:"The North is the south.".hello:function(){
        console.log(this + "says hello"+ thing); }}// Simplified syntax
person.hello("world");
// Core syntax /
person.hello.call(person,"world");

Copy the code

Note: This simplification is independent of how member functions are assigned and defined. In the example above, for example, member functions are defined directly in the object. If member functions are assigned dynamically, the resulting simplification is the same.

function hello(thing){
    console.log(this + "says hello" + thing);
}

person = { name:"The North is the south."};
person.hello= hello;
// Simplify the syntax
person.hello("world") // The core syntax of this type is' person.hello.call(person,'world') '

hello("world") //"[object DOMWindow]world"
Copy the code

Note: The value of this in all of the above functions is not deterministic. The value of this is determined by the scope in which the function is called.

withFunction.prototype.bindBind the scope

In some scenarios, the value of this in a function may need to be bound to the specified environment. An additional function is required for context-specific bindings.

var person ={
    name:"The North is the south.".hello:function(thing){
        console.log(this + "says hello "+ thing); }}var boundHello = function(thing){
    return person.hello.call(person,thing);
}

boundHello("world");

Copy the code

Although boundHello(“world”) is desugared (desugar) to boundHello.call(window,”world”) when called. But inside the function, we treat hello, a member of the Person object, as this, pointing to the scope where hello should be.

Or we could make the boundXX function more generic.

var bind = function(func,thisValue){
    return function() {return func.apply(thisValue,arguments);
    }
}

var boundHello = bind(person.hello,person);
boundHello("world");
Copy the code

The principle of implementation is not described here.

Because there are so many of these scenarios, ES5 added the bind method to the Function object to specify a specific this value for a Function.

var boundHello = person.hello.bind(person);
boundHello("world");

Copy the code

This is useful, for example, if you call a member function as a callback:

var person = {
  name: "The North is the south.".hello: function() { console.log(this.name + " says hello world"); }} $("#some-div").click(person.hello.bind(person));

Copy the code

Clear the clouds and see the moon

Above, in order to be able to explain the core mechanism of function calls in the existing canonical syntax. Func. Call is used to illustrate how the underlying function implements a series of data operations. In fact, there is another person [[Call]] who implements the core syntax for function calls (which is an internal property), but it is a fundamental part of the func. Call, [obj.]func() implementations.

Let’s look at the definition of func.call

  1. iffuncNot a function that throws an error.
  2. I’m going to define a zeroargList
  3. If more than one argument is passed to the function, take the first argumentarg1The values of all arguments to the end of the argument are treated as a new value,The assignmenttoargList.
  4. Return the result of calling the [[Call]]Internal method of func, providing thisArg as the this value and argList as the list of arguments. The original sentence is more appropriate.

As defined above, the internal implementation of func.call is based on the operation [[call]]. That is, the core of a function Call is the implementation of **[[Call]]**. But this method is implemented in the same way that func.call is handled. So, through analogy to simulate the function call process.