1
参考

【第1318期】深入浅出 JavaScript 关键词 -- this
https://juejin.cn/post/684490...

写这篇文章原因

因为总结面经中遇到了this的指向问题,这也是面试官常问的基础问题。所以单独列出来供参考学习

this指向几点判断规则

js的函数除了声明定义的形参之外,每个函数还接受两个附加参数:this和arguments。this 的值并不是由函数定义放在哪个对象里面决定,而是函数执行时由谁来唤起决定。

  1. 函数调用模式:strict情况下,指向undefined,否则指向全局变量
  2. 方法调用模式:指向方法所在的对象
  3. 构造函数模式调用,用new时,this指向新构建的对象
  4. apply,call明确绑定: 或者bind绑定,this指向被绑定的对象
  5. 箭头函数内部的this就是外层代码块的this,包裹在函数中时this指向函数调用时所在的对象,若放在全局中则是指向全局对象window,且不会改变

    // Q1 规则1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window
    var a = 1;
    function print () {
     console.log(this.a)
    }            
    print()  //a=1
    
    // Q2 规则2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
    const obj = {
     a: 2,
     print: function () { console.log(this.a) }
    }
    obj.print();  //2
    ​
    // Q3 
    const obj = {
     a: 3,
     print: function () { console.log(this.a) }
    }
    obj.print()  //3  与下面的foo()区别在于是全局环境还是obj环境
    const foo = obj.print; 
    foo()     //undefined      全局情况下调用的,没有全局变量a
    
    // Q3.1   如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象
    const obj = {
     a: 3,
     printOut:{
         a:4,
         printIn: function(){ console.log(this.a)},
     },
    }
    obj.printOut.printIn()    //4 
    const foo = obj.printOut.printIn;  
    foo()     //undefined      全局情况下调用的,没有全局变量a
    ​
    // Q4  Q4-Q9参见规则5
    const obj = {
     a: 4,
     print: () => { console.log(this.a) }
    }
    obj.print();                 //undefined     有箭头函数,对象不构成单独的作用域,导致`print`箭头函数定义时的作用域就是全局作用域。
    ​
    // Q5
    var a = 5
    const obj = {
     a: 6,
     print: () => { console.log(this.a) }
    }
    obj.print.call({a: 7}); //5         理由同上
    ​
    // Q6 
    function Person () {
     this.a = 8
     this.print = function () {console.log(this.a)}
     return {a: 9} 
    }
    const p = new Person()  
    console.log(p.a)  //9   此时p为构造函数返回的{a:9}
    console.log(p.print())  // undefined p是没有print函数的
    ​
    // Q7 
    'use strict';
    var a = 1;
    ​
    function print () {
     console.log(this.a)
    }
    print()    //undefined 严格模式下,this指向undefined
    
    // Q8 普通函数
    function foo() {
      setTimeout(function() {
     console.log('id:', this.id);
      });
    }
    var id = 21;
    foo.call({ id: 42 }); //21 setTimeout是延迟函数,在foo被调用后才执行,这时候this指向window
    
    //Q9 箭头函数,匿名函数定义时所在的执行环境就是foo函数,所以匿名函数内部的this执向始终会和foo函数的this执向保持一致,指向call的对象。
    为什么指向call的对象呢?参见call的用法:函数名.call(对象,arg1,arg2,...argn),功能是调用函数,并把函数内部的this指向第一个参数的对象,然后将第二个及之后的是所有的参数,作为实参传给函数。
    function foo() {
      setTimeout(() => {
     console.log('id:', this.id);
      }, 100);
    }
    
    var id = 21;
    foo.call({ id: 42 }); //42
    
    function foo() {
      setTimeout(() => {
     console.log('id:', this.id);
      }, 100);
    }
    
    var id = 21;
    foo(); //21(没有用call)
    
    // Q10
    var A = function( name ){ 
     this.name = name;
    };
    var B = function(){ 
     A.apply(this,arguments);
    };
    B.prototype.getName = function(){ 
     return this.name;
    };
    var b=new B('sven');
    console.log( b.getName() ); // 输出:  'sven'
    

---更新,今天看了闭包,有了新的认识

//1
var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
var a = object.getNameFunc;
a()();//这里的调用者一直是window,因此输出"The Window";
object.getNameFunc()();//这里object.getNameFunc()时调用者是object,但是将object.getNameFunc()作为一个整体,他的调用者是window,是window来调用object.getNameFunc()(),此时调用者是window,因为输出"The Window";


//2
 var name = "The Window";
  var object1 = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
  object1.getNameFunc()();//这里类似上面object.getNameFunc()时调用者是object的,但是在object1.getNameFunc()的返回函数中,将this赋值给that,因此object1.getNameFunc()()中,this仍然是object,所以输出"My Object",
var e = object1.getNameFunc;
e()();//这里this一直是window,因此不管如何赋值,都输出"The Window"


//3
var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        return this.name;
    }
};
object.getNameFunc()
//"My Object"
(object.getNameFunc)()
//"My Object"
(object.getNameFunc = object.getNameFunc)()
//"The Window"
//最后一个object.getNameFunc的值是函数本身。function (){return this.name;}

九是我呀
19 声望1 粉丝

希望每写一篇优质文章,工资就涨100元。