What usage scenarios does this have? What's the difference from this in C,Java? How to change the value of this?

Keywords: Attribute


Seven usage scenarios of this

This is usually used inside a function to represent the environment object in which the function is located. It can only be determined when the function is running. The values of this corresponding to different invocation methods are different.

Scenario 1: Global & Calling Common Functions

In a global environment, this always points to window.


console.log(this === window);     //true

When a normal function is called (note that it is not a constructor, and no new is added before it), this also points to window.

var x = 10;
function foo(){
    console.log(this);     //Window
    console.log(this.x);   //10
}
foo();

Case 2: Constructor

The so-called constructor is an object that comes out of a function new, and this points to a new object. Generally, the function name of the constructor is capitalized, such as Object, Function and Array, which belong to the constructor.

function Foo(){
    this.x = 10;
    console.log(this);    //Foo {x:10}
}
var foo = new Foo();
console.log(foo.x);      //10

The above code, if the function is used as a constructor, then this represents the object that it will be new out of.

But if you call the Foo function directly instead of the new Foo(), it becomes case 1, and then Foo() becomes a normal function.

function Foo(){
    this.x = 10;
    console.log(this);    //Window
}
var foo = Foo();

Case 3: Object approach

If a function is a method of an object, this in the method points to that object.

var obj = {
    x: 10,
    foo: function () {
        console.log(this);        //Object
        console.log(this.x);      //10
    }
};
obj.foo();

Note: If you define functions in object methods, the situation is different.

var obj = {
    x: 10,
    foo: function () {
        function f(){
            console.log(this);      //Window
            console.log(this.x);    //undefined
        }
        f();
    }
}
obj.foo();

It can be understood that although function f is defined in obj.foo, it still belongs to a common function, and this still points to window.

Here, if you want to call the variable obj.x in the upper scope, you can use self to cache the external this variable.

var obj = {
    x: 10,
    foo: function () {
        var self = this;
        function f(){
            console.log(self);      //{x: 10}
            console.log(self.x);    //10
        }
        f();
    }
}
obj.foo();

If the foo function is not called as an object method:

var obj = {
    x: 10,
    foo: function () {
        console.log(this);       //Window
        console.log(this.x);     //undefined
    }
};
var fn = obj.foo;
fn();

obj.foo is assigned to a global variable and is not called as an attribute of obj, so the value of this is window.

Scenario 4: Constructor prototype attribute

function Foo(){
    this.x = 10;
}
Foo.prototype.getX = function () {
    console.log(this);        //Foo {x: 10, getX: function}
    console.log(this.x);      //10
}
var foo = new Foo();
foo.getX();

In the Foo.prototype.getX function, this points to the foo object. Not only that, but even in the entire prototype chain, this represents the value of the current object.

Case 5: Functions are called with call, apply, or bind.

var obj = {
    x: 10
}
function foo(){
    console.log(this);     //{x: 10}
    console.log(this.x);   //10
}
foo.call(obj);
foo.apply(obj);
foo.bind(obj)();

When a function is call ed, applied, or bind, the value of this takes the value of the incoming object.

Case 6: DOM event this

In an HTML DOM event handler, this always points to the HTML DOM node bound by the handler:

function Listener(){   
    document.getElementById('foo').addEventListener('click', this.handleClick);     //Here this points to the Listener object. What is not emphasized here is this.
}
Listener.prototype.handleClick = function (event) {
    console.log(this);    //<div id="foo"></div>
}
var listener = new Listener();
document.getElementById('foo').click();

This is a good understanding, which is equivalent to passing parameters to the function, changing the handleClick runtime context, equivalent to the following code:

var obj = {
    x: 10,
    fn: function() {
        console.log(this);         //Window
        console.log(this.x);       //undefined
    }
};
function foo(fn) {
    fn();
} 
foo(obj.fn);

You can also switch context by bind:

function  Listener(){
    document.getElementById('foo').addEventListener('click',this.handleClick.bind(this));      
}
Listener.prototype.handleClick = function (event) {
    console.log(this);    //Listener {}
}
var listener = new Listener();
document.getElementById('foo').click();

The first six cases can be summarized as follows: this points to the object calling the method.

Case 7: this in the arrow function

When using the arrow function, the situation is different: this inside the arrow function is lexical scope, determined by the context.

var obj = {
    x: 10,
    foo: function() {
        var fn = () => {
            return () => {
                return () => {
                    console.log(this);      //Object {x: 10}
                    console.log(this.x);    //10
                }
            }
        }
        fn()()();
    }
}
obj.foo();

Now, the arrow function completely fixes the direction of this, which always points to the lexical scope, that is, the outer caller obj.

If the arrow function is used, the previous hack notation is as follows:

var self = this;

No more.

var obj = {
    x: 10,
    foo: function() {
        var fn = () => {
            return () => {
                return () => {
                    console.log(this);    // Object {x: 10}
                    console.log(this.x);  //10
                }
            }
        }
        fn.bind({x: 14})()()();
        fn.call({x: 14})()();
    }
}
obj.foo();

Since this is already bound in the arrow function according to the lexical scope, when calling the arrow function with call() or apply(), it is impossible to bind this, that is, the first parameter passed in is ignored.


How to change the value of this

First: new keywords change this direction

//Constructor version this
function Fn(){
    this.user = "Pursue dreams";
}
var a = new Fn();
console.log(a.user); //Pursue dreams

An instance of Fn is created with variable a (equivalent to copying a Fn into object a), which is only created and not executed at this time. The function Fn is called by object a, so this naturally points to object a, so why there are user s in object a, because you have copied a Fn function into object a, and using new keyword is equivalent to copying a copy.

Second: call () fun.call(this value, parameter list)

var a = {
    user:"Pursue dreams",
    fn:function(){
        console.log(this.user); //Pursue dreams
    }
}
var b = a.fn;
b.call(a);  //If call is not used, then this after b() execution refers to a Window s object

Add b to the environment of the first parameter, and in short, this points to that object.

In addition to the first parameter, the call method can also add several parameters, as follows:

var a = {
    user:"Pursue dreams",
    fn:function(e,ee){
        console.log(this.user); //Pursue dreams
        console.log(e+ee); //3
    }
}
var b = a.fn;
b.call(a,1,2);

Third: apply () fun.apply(this value, parameter array)

var a = {
    user:"Pursue dreams",
    fn:function(){
        console.log(this.user); //Pursue dreams
    }
}
var b = a.fn;
b.apply(a);

apply method is similar to call method. It can also change the direction of this. It can also have multiple parameters, but the difference is that the second parameter must be an array, as follows:

var a = {
    user:"Pursue dreams",
    fn:function(e,ee){
        console.log(this.user); //Pursue dreams
        console.log(e+ee); //11
    }
}
var b = a.fn;
b.apply(a,[10,1]);
//Notice if call and apply The first parameter isnull,thatthisPointing towindowobject
var a = {
    user:"Pursue dreams",
    fn:function(){
        console.log(this); //Window {external: Object, chrome: Object, document: document, a: Object, speechSynthesis: SpeechSynthesis…}
    }
}
var b = a.fn;
b.apply(null);

Fourth: bind () fun.bind(this value, parameter list)
There are some differences between bind method and call and apply method, as follows:

var a = {
    user:"Pursue dreams",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
b.bind(a);  //Code not printed

We found that the code was not printed. Yes, that's the difference between the bind method and the call and apply method. In fact, the bind method returns a modified function for subsequent calls.

var a = {
    user:"Pursue dreams",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
var c = b.bind(a);
console.log(c); //function() { [native code] }

Function c. See if you can print out the user in object a.

var a = {
    user:"Pursue dreams",
    fn:function(){
        console.log(this.user); //Pursue dreams
    }
}
var b = a.fn;
var c = b.bind(a);
c();

Similarly, bind can have multiple parameters, and the parameters can be added again when they are executed, but it should be noted that the parameters in subsequent calls to new functions are arranged behind the existing parameters, and the parameters are in the order of the parameters.

var a = {
    user:"Pursue dreams",
    fn:function(e,d,f){
        console.log(this.user); //Pursue dreams
        console.log(e,d,f); //10 1 2
    }
}
var b = a.fn;
var c = b.bind(a,10);
c(1,2);

Summary: Both call and apply change this in context and execute this function immediately. The bind method allows the corresponding function to be called whenever it wants to be tuned, and can add parameters when it executes. This is the difference between them.


Posted by jigsawsoul on Sun, 16 Dec 2018 09:51:03 -0800