一文总结JavaScript中this指向问题

612 阅读2分钟

今天闲极无聊整理一下JavaScript中的this指向问题,希望对初学者有所帮助,大佬自动跳过

JEE:this指针又叫“上下文对象”,指向代码的执行环境对象 从以下几个常见场景归类

函数调用

当this出现在全局环境下的函数中,this指向宿主环境(浏览器下是window)

function sayName() {
    this.name = '子落';
    console.log(this.name);
}
sayName();//子落

在window环境下调用函数,this指向window对象,上面写法等同于

var name = '子落'
function sayName() {
    //或者 name = '子落' (函数中声明变量时没有var,变量默认声明为全局变量)
    console.log(this.name);
}
sayName();//子落

⚠️注意区分下面这种写法

function sayName() {
    var name = '子落';
    console.log(this.name);
}
sayName();ReferenceError资源不存在错误(由于在window对象中不存在name属性)

对象方法

当this出现在某个对象方法中时,this指向这个对象

var name = 'window';
var obj = {
    name: '子落',
    sayName: function() {
        console.log(this.name)
    }
};
obj.sayName() //子落

⚠️注意区分下面这种写法

var name = 'window';
var obj = {
    name: '子落',
    sayName: function() {
        console.log(this.name);
    }
};
var ss = obj.sayName;  
ss();   //window

对象方法是在window环境下被当作函数调用,此时this指向window

构造函数

当this出现在构造函数中时,this指向新创建的对象实例

function Person() {
    this.name = '子落'
}
//或者es6的class写法
class Person {
  constructor() {
    this.name = '子落'
  }
}
var person = new Person();
console.log(person.name)//子落

call,apply,bind

当this出现在call,apply,bind等函数调用环境中时,this指向传入的第一个对象参数,不传时默认值是window

var name = 'window'
var person = {
    name: '子落'
};
function sayName() {
  console.log(arguments)  //{ '0': 1, '1': 2, '2': 3 }
  console.log(this.name)
}
sayName.apply(person)   //子落(传递person作为执行环境,下同)
sayName.call(person)   //子落
const say = sayName.bind(person, 1, 2, 3)
say() //子落
//不传参数是默认的执行环境是全局环境window
sayName.apply()    //window

箭头函数

当this出现在箭头函数中时,this指向外层函数的执行环境

var name = 'this is window'
var person = {
  name: '子落',
  sayName: () => {
    console.log(this.name)
  },
  hello() {
    const bibao = () => {
      console.log(this.name);
    }
    bibao()
  }
}
person.sayName() //this is window
person.hello()  //子落

顺便提一下箭头函数的几个特点:

  1. 无this指针;
  2. 无arguments;
  3. 不能作为构造函数;
  4. 函数内不能出现yield

特殊场景

除了上面列出的几种this指向,还有一些特殊场景,this总是指向window

匿名函数自调
var name = '子落';  
var person ={  
     name : 'person子落',  
     showName : function(){  
         alert(this.name);  
     },  
     waitShowName : function(){  
         !function(__callback){
            alert(this.name); 
        }();  
     }  
 };  
 person.showName()   //person子落
 person.waitShowName()  //子落
定时任务(setTimeout、setInterval)
var name = '子落';   
var person ={  
    name : 'person子落',   
    showName : function(){  
        alert(this.name);  
    },  
    waitShowName : function(){
        setTimeout(function(){
            this.showName();
        }, 1000);
    }
}; 

person.waitShowName();  //子落

⚠️注意,当定时任务传入的是一个箭头函数时,this并不会指向window

var name = 'this is window'
var person = {
  name: '子落',
  sayName() {
    setTimeout(() => {
      console.log(this.name)
    }, 0)
  }
}
person.sayName()  //子落
//由于箭头函数本身没有this指针,箭头函数的this指针是外部函数的this指针(sayName)
//sayName是通过person对象调用的,所以this.name="子落"

综上可以总结:谁调用这个函数或方法,this关键字就指向谁