[Interview required points] This time I will take you to thoroughly learn the pointing questions of this


foreword

I believe that many friends, like me, are always confused about the direction of this. Since there is no rigid requirement, they always don’t want to study. After two interviews, the author found that this test site is really the point that interviewers often test. Let’s calm down and study the direction of this this together !


文章主体内容分为两块:this的指向以及如何改变this的指向

1. The pointing problem of this

1.1 this in the global

The global this points to window

    // 1. 全局中的this
    console.log(this) // window

1.2 this in ordinary functions

This in a normal function points to the caller

	function fn() {
    
    
	      console.log(this) // window
	   }
	 fn()  // window.fn(),window调用了fn函数,所以fn中的this表示window

In fn() here, the caller is actually window, but it is window.fn() , and window is omitted

    let obj = {
    
    
        name : '前端百草阁',
        fn: function(){
    
    
            console.log(this.name)
        }
    }
    obj.fn() // 输出结果: 前端百草阁

The fn caller here is the object obj, so this.name is equivalent to obj.name

1.3 this in the timer

This in the timer points to the global object window

	function sayHello() {
    
    
	  console.log(this);
	}
	
	setTimeout(sayHello, 1000); // window

1.4 this in the event handler function

This in the event handler function points to the event source

   document.body.addEventListener('click', function () {
    
    
      console.log(this) // body
    }) 

When the click event is triggered, print the body. In this example, the event source is body, so this points to the event source (body)

1.5 this in the constructor

this in the constructor points to the instantiated object

	function Dog(age) {
    
    
	      this.age = age
	      this.say = function () {
    
    
	        console.log(this)
	        console.log(this.age)
	      }
	   }
	   
	   //利用构造函数创建实例化对象dog
	    let dog = new Dog()
	    dog.say()  // 输出结果: 
	    		   //			Dog {age: 3, say: ƒ}
	               //           3

The dog here is an instantiated object, so this in the constructor is equivalent to the instantiated object of dog.
Some students may be a little confused. Here, everyone must remember that the this point is determined at runtime, not at the time of definition. The
code instantiates a dog object at runtime. At this time, this points to the instantiated object. It does not mean that this is determined when the constructor is defined.

It is worth mentioning that if you add another method to the prototype object of the constructor, this still points to the instantiated object

	function Dog(age) {
    
    
	      this.age = age
	      this.say = function () {
    
    
	        console.log(this)
	        console.log(this.age)
	      }
	   }
	Dog.prototype.eat = function () {
    
    
      console.log(this)
    }
	   //利用构造函数创建实例化对象dog
	    let dog = new Dog()
	    dog.say()  // 输出结果: 
	    		   //			Dog {age: 3, say: ƒ}
	               //           3
	    dog.eat()  // 输出结果: Dog {age: 3, say: ƒ}

1.6 this in constructor static method

In the static method of the constructor, this represents the constructor

	//	 构造函数Pig
		function Pig() {
    
    
	 
	  	 }
	    // 给构造函数,直接添加的方法,叫做静态方法
	    Pig.eat = function () {
    
    
	      console.log(this)
	    }
	    // 调用的时候,只能使用构造函数调用
	    Pig.eat() // 输出结果: ƒ Pig() { }

1.7 this in arrow function

The arrow function does not have its own this value, it will inherit the this of the outer scope

  var age = 10
    let obj = {
    
    
      age: 20,
      say: () => {
    
    
        console.log(this.age) // 10
      }
 }

obj.say()

Do you think this.age is 10 or 20?
The arrow function here does not have this, but it will inherit the this of the outer scope. Here, outside the scope of the arrow function, it is the global scope window. Many people may think why it is not the local scope of obj? because! ! The curly braces of the object cannot be regarded as a scope , so this.age
here is equivalent to window.age , which is 10 and another example

 var age = 10
 let obj = {
    
    
      age: 20,
      eat: function () {
    
    
        let fn = () => {
    
    
          console.log(this.age) // 箭头函数中没有this,所以这里的this指向eat方法中的this,即obj
        }
        fn()
      }
   }

obj.eat()

Here this in the arrow function points to this in the eat method , and this in eat points to the obj object, so the output here is 20
insert image description here

2. Modify the this point in the function

The callers of the three methods described next must be functions

2.1 call

The syntax of call: function.call(new this, 3, 4) , where 3, 4 represent the passed parameters, and 34 is easy to understand

let obj = {
    
     age: 20 }
 
function fn(x, y) {
    
    
    console.log(this)
    console.log(x + y)
  }
fn(34) // 正常调用函数,函数中的this指向 window
fn.call(obj, 3, 4)
    // 总结:
    // 1. 函数.call() 表示调用函数,原函数fn得以调用了
    // 2. 修改了原函数中的this,改成call方法的第一个参数
    // 3. 如果原函数有形参,可以通过call方法为原函数传递实参

fn.call(obj,3,4) , when the call function is called, the original this (pointing to window) in fn is changed to a new this (pointing to obj), 3 and 4 respectively represent the parameters to be passed by x and y
insert image description here

2.2 apply

The syntax of apply: function.apply(new this, [3, 4]) , where 3 and 4 represent the passed parameters, and 34 is easy to understand

let obj = {
    
     age: 20 }
 
function fn(x, y) {
    
    
    console.log(this)
    console.log(x + y)
}
fn(34)
fn.apply(obj, [3, 4])
    // 总结:
    // 1. 函数.apply() 表示调用函数,原函数fn得以调用
    // 2. 修改了原函数中的this,改成 apply 方法的第一个参数
    // 3. 如果原函数有形参,可以通过 apply 方法为原函数传递实参,但是必须使用数组格式(这也是与call方法的区别)

insert image description here

2.3 bind

The usage of bind is quite different. Let’s first look at the characteristics of the bind function
. 1. The function .bind() means that a new function is created and will not call any function.
2. The this in the new function is modified and changed to the first parameter of the bind
method

.

let obj = {
    
     age: 20 }
function fn(x, y) {
    
    
    console.log(this)
    console.log(x + y)
}
let a = fn.bind(obj, 3, 4)
a()

Here because fn.bind() will not call any function, so you have to call it yourself,
you can also write like this

let obj = {
    
     age: 20 }
function fn(x, y) {
    
    
    console.log(this)
    console.log(x + y)
}
fn.bind(obj, 3, 4)()

insert image description here

3. this points to practice

3.1 Written test questions for a small game company

Please think about the answer first, and then read the explanation

        let obj = {
    
    
            stringName : "我是abc",
            getName(){
    
    
                return function(){
    
    
                    return this.stringName
                }
            }
        }
        console.log(obj.getName()()); // undefined

To find the this point of an ordinary function, you must know who the caller is. Many people in this written test question will be misled, thinking that the callers are all obj . In fact,
I will write it differently, and everyone will know it at a glance.

        let obj = {
    
    
            stringName : "我是abc",
            getName(){
    
    
                return function(){
    
    
                    console.log(obj.getName);
                    return this.stringName
                }
            }
        }
        let fn = obj.getName()
        console.log(fn()) // undefined

These two methods are exactly the same, so everyone can tell the difference at a glance? The return value of the method of calling the object, this points to the global object window !. This is because the returned function is called as a global function, not as a method of obj
Next, let's see how to read the srtingName in obj?

        let obj = {
    
    
            stringName : "我是abc",
            getName(){
    
    
                let that = this
                return function(){
    
    
                    return that.stringName
                }
            }
        }
        console.log(obj.getName()());

Here is the difference from the above: a variable that is used here to store this in getName, and the caller of getName is obj, which is equivalent to using a that to store a this and pointing to obj , so the running result is:
insert image description here

3.2 Dachang written test questions

Handwritten implementation of call function

    Function.prototype.myCall = function(context, ...args) {
    
    
        // 判断是否传入了context,如果没有则默认为全局对象
        context = context || window;

        // 将当前函数设置为context的一个属性,以便调用时可以通过context调用
        context.fn = this;

        // 调用函数并传入参数
        const result = context.fn(...args);

        // 删除context的fn属性
        delete context.fn;

        // 返回函数的执行结果
        return result;
};
    function greeting(name) {
    
    
    console.log(`Hello, ${
      
      this.name + name}!`);
}
    let a = {
    
    
        name: "前端"
    }
    greeting.myCall(a,'百草阁');
};

insert image description here
Implementation points: 1. The function needs to be called 2. The point of this needs to be changed 3. How to change the point of this when passing parameters
? Please pay attention to the line context.fn = this , what this points to is actually the greeting function, which is equivalent to the original window.greeting() call, and now the function is called as an attribute of the context, and this points to this context, changing the calling method of the original greeting function, thereby changing the direction of this

Summarize

This article focuses on explaining various usage scenarios of this , how to change the direction of this in a function , and practice questions of this.
In fact, many times we will encounter various this problems in various scenarios, but we all choose to muddle through and don’t want to spend time to understand. Why not learn this comprehensively with the author this time, which is a must for the interview!

Guess you like

Origin blog.csdn.net/m0_57524265/article/details/131624968