Preface: Hello everyone, I am Lin Yiyi, this is an article about this pointing. This is a particularly important knowledge point in JS, is this difficult? It seems pretty simple. After reading this article, if you still can’t, you don’t come to me. Manual dog head 🐕.

Mind mapping

This point

  • Before the function is executed'. 'Dot operator, in the body of the functionthisI’ll just point to the previous object, and if I don’t, I’ll point to itwindow, pointing in strict modeundefined. This sentence is particularly important, please remember
  • The function has no direct callerthisPoint to a global object (Window in the browser, global in Node). Such as anonymous functions
  • constructionalthisPoint to the instance itself.
  • The arrow function itself does notthisOf the arrow functionthisPoints to the nearest non-arrow functionthisIf you can’t find it, pointwindow, pointing in strict modeundefined.

Consider this statement again: there is before the function is executed'. 'Dot operator, in the body of the functionthisI’ll just point to the previous object, and if I don’t, I’ll point to itwindow

This is an ordinary function

Warm up the topic 1

var name = 'Lin Yiyi'
function fn(){
    var name = 'Forest two two'
    return this.name
}
fn()    / / linyi
Copy the code

Call fn() without the ‘.’ operator, so this refers to the window. The output is the global name = ‘lin-one-one’.

Consider this statement again: there is before the function is executed'. 'Dot operator, in the body of the functionthisI’ll just point to the previous object, and if I don’t, I’ll point to itwindow

Warm-up questions 2

var name = 'Forest two two'
var obj = {
    name: 'Lin Yiyi'.fn: function () {
        return this.name
    }
}
console.log(obj.fn())   // 'linyiyi'
var fo = obj.fn
console.log(fo())       // 'lin2' fo() ==> window.fo()
Copy the code

The function fn() in obj.fn() is preceded by the ‘.’ operator, so this refers to obj. The fo() function is not preceded by the ‘.’ operator, so this refers to the window. Fo () ==> window.fo(); fo() ==> window.fo()

Consider this statement again: there is before the function is executed'. 'Dot operator, in the body of the functionthisI’ll just point to the previous object, and if I don’t, I’ll point to itwindow

Warm-up problem 3. Modify warm-up problem 2

var name = 'Forest two two'
var obj = {
    name: 'Lin Yiyi'.fn: function () {
        var name = 'small three'
        return function(){
             return this.name
        }
    }
}
console.log(obj.fn()())   / / Lin.
var fo = obj.fn()
console.log(fo())    / / Lin.
Copy the code

Obj.fn ()() returns A function (called function A), and A() does not have A ‘.’ operator, so this refers to the window. The output is Lin22. The fo() function above is the same.

Function has no direct caller (update)

The function has no direct callerthisPoints to global objects (window in browser, global in Node), such as anonymous functions; Pointing in strict modeundefined

Warm up the topic 1

var name = 'Lin Yiyi'; ! (function(){
   console.log(this.name)   / / linyi}) ()Copy the code

The self-executing function has no direct caller output name = ‘lin-one-one’.

Warm-up questions 2

var name = 'Lin Yiyi'
var obj = {
    name : '二二'.callback: function(){
        console.log(this.name)
    }
}

setTimeout(obj.callback,1000)
/* Output * linyi */
Copy the code

The setTimeout, obj.callback(which is just a reference address) functions do not have a direct caller; this refers to the window. So the output name is Lin Yiyi in the global context.

Constructor this

Read this sentence: constructorthisPoint to the instance itself

Why this point about the constructor browser instance is specified, see new | you have to understand what has happened to this process interview JS prototype and prototype chain

Warm up the topic 1

function Fn(){
    var n = 0
    this.name = 'Lin Yiyi'
    this.age = 18
    this.getName = function(){
        return this.name
    }
}

Fn.prototype.getAge = function(){
    return this.age
}

Fn.x = 'Forest two two'

var f = new Fn()
console.log(f.name)     / / linyi
console.log(f.getName())     / / linyi
console.log(f.getAge())        / / 18
console.log(f.n)    // undefined
console.log(f.x)    // undefined
Copy the code

Fn above is a constructor when new, and this refers to instance f. So the 1,2 output above is Lin 1, 1. F getAge() is 18. F getAge() is 18. F getAge() is 18. A: this is the prototype chain lookup mechanism, properties of x is not on the prototype prototype is not instance attributes, you can read this article interview | you have to know the JS prototype and prototype chain; Q: why is the output of f.n undefined? Because the variable n is private to the constructor and has nothing to do with the instance new creates.

Arrow function

  • The arrow function itself does notthisOf the arrow functionthisInheriting context, insidethisWill point to the current nearest non-arrow functionthisIf I can’t find itwindow(The strict mode is undefined)
  • The arrow function’s this is defined, not executed

Warm up the topic 1

var name = 'Lin Yiyi'
var obj = {
    name: '二二'.a: () = > {
        console.log(this.name)
    }
}
obj.a()

/* output * 'linyiyi' */
Copy the code

This of the arrow function. If you can’t find this of the non-arrow function, you point directly to the window.

Warm-up questions 2

var name = 'Lin Yiyi'
var obj = {
    name: '二二'.fn: function() {
        return () = > {
            console.log(this.name)
        }
    }
}
obj.fn()()

/* Outputs * 'two two' */
Copy the code

It is clear that the arrow function’s this comes from fn, and the object obj calls fn, so fn’s this points to obj, and the output is 2, 2.

Change the direction of this

Tip: All functions are based onFunctionThis base class to create, also ownsFunctionThe method above the prototype

  • callAnd acceptthisObject, and a set of lists.applycallSame thing, with the only differenceapplyYou accept an array of multiple parameters.bindIt also changes the functionthisPoint to, nothing morebindExecution returns a new function whose arguments are derived from the remaining arguments

Warm up the topic

var name = 'Lin Yiyi'
var age = 18
function fn(){
   return this.name
}

function p(){
    return {
        age: this.age,
        arg: arguments}}let obj = {
    name: '二二'.age: 18
}

let o = {
    name: 'since'
}

fn()    // 'linyiyi'
fn.call(obj)    // '2 2'
fn.call(o)  //  '三三'
p.call(obj, 12.23.45.67) // {age: 18, arg: Arguments(4)}

fn.apply(obj)    // "two two"
p.apply(obj, [1.2.3.4.5])    // {age: 18, arg: Arguments(5)}

fn.bind(obj)()  // "two two"
p.bind(obj, 12.23.34) ()// {age: 18, arg: Arguments(3)}
Copy the code

That’s call, apply, and bind. I won’t write this here. If I do, I’ll write another article. Those who are not familiar with these 3 can look for other data.

To consider

1. What does this mean

var name = 'Lin Yiyi'
var obj = {
    name: 'Forest two two'.show: function (){
        console.log(this.name)
    },
    wait: function () {
        var fn = this.show
        fn()
    }
}
obj.wait()  / / linyi
Copy the code

Obj.show ==> obj.show ==> obj.show ==> obj.show ==> obj.show If fn() is not preceded by the ‘.’ operator, then this refers to the window and the output is Lin yiyi.

2. Ali This Point and Prototype interview questions (added)

What happens when you create a new functionThe interview | you have to know the JS prototype and prototype chain

function Foo() {
    Foo.a = function() {
        console.log(1)}this.a = function() {
        console.log(2)
    }
}

Foo.prototype.a = function() {
    console.log(3)
}

Foo.a = function() {
    console.log(4)
}

Foo.a();

let obj = new Foo(); 
obj.a();
Foo.a();
/* * 4 * 2 * 1 */
Copy the code

Foo.a(); The private method a that calls the function directly in the. new Foo(); The function’s private a is reassigned, along with the property a on prototype. So the obj. (a); The output is 2, foo.a (); The output is 1.

3. This pointing problem with closures

var n = 2 // -> 4 -> 8
var obj = {
    n: 3./ / 6
    fn: (function(n){
        n*=2
        this.n+=2    // N under window becomes 4
        var n = 5    // This step will not be redeclared, because the argument is already assigned, it will not be declared, but will be directly assigned n = 5
        console.log("window.n".window.n)
        return function (m) {
            console.log("n:", n, "m", m)    // n:5 m:3 where n up is 5 //
            this.n*=2    // fn(3): 2 * 4 =8 // obj.fn(3): 2 * 3 = 6
            console.log(m + (++n))    // 3 + (++5) ++n causes the upper scope n to become 6 // 3 + (++6)
        } 
    })(n)
}

var fn = obj.fn;
fn(3)    / / 9
obj.fn(3)    / / 10
console.log(n, obj.n)    / / 6
/* Output * 9 * 10 * 8 6 /Copy the code

This problem is left to everyone to think about, above have my analysis steps, feel eyesore words can be removed 😂. You can give your analysis in the comments section.

The end of the

Thank you for reading early here, I am Lin Yiyi, if this article can inspire you a little, welcome to give astarSee you next time.