this的指向在JS中是一个绕不过而且容易绕迷的问题,今天就this的指向问题,让我们从内存数据储存的角度去剖析一下。
直入主题,JS中,函数可以在不同的运行环境执行,为了获取当前函数执行的环境,this就应运而生。this设计的目的,就是在函数体的内部,可以获取函数当前的运行环境。由于函数的执行环境复杂且多变,导致很多同学被this搞得是晕头转向,所以,只有从根本上去分析问题,才能从根本上去解决问题,任由外界环境多复杂,抓住了根本,就永远都不会迷失。
举个栗子,下列函数调用方式和执行结果如下:
function oneFun() {
console.log('this1', this);
}
const funObj = {
fun1: function () {
console.log('this2', this);
},
fun2: () => {
console.log('this3', this);
},
}
oneFun();//this1 window
funObj.fun1();//this2 funobj
const funFromObj1 = funObj.fun1;
funFromObj1();//this2 window
funObj.fun2();//this3 window
const funFromObj2 = funObj.fun2;
funFromObj2();//this3 window
看到这个结果,你也许会有以下疑问:1、function函数的this由调用环境决定的,为什么赋值给其他变量再调用,会指向window呢?箭头函数的this在声明时就确定了,为什么在funObj对象中声明,上边两种调用模式的this指向还是window?下边咱们从内存中的数据存储的方向来解析分别一下(暂只分析非严格模式下的情况)。
首先,对于this指向,MDN中是这么说的:对于function声明的普通函数,this指向当前函数执行的环境对象;箭头函数的this被设置为他被创建时的环境对象。
图一
1、图一中,oneFun函数在window对象中声明和调用,在非严格模式下直接调用,默认是通过window.oneFun()的形式调用,故其this指向了window。
图二
2、代码栗子中,看上去funObj中声明了两个函数,function关键字函数fun1和箭头函数fun2。其实两个函数在内存中都独立占据了一块区域,只不过对象的fun1和fun2属性指向了他们储存的区域,两个函数的声明环境都是在window对象中(如图二)。当通过funObj.fun1调用普通函数时,是直接通过funObj.fun1指向了函数并进行调用,故其this指向funObj;当使用变量funFromObj1接收一下funObj.fun1时,其本质为funFromObj1直接指向了function函数所在的内存地址,是通过funFromObj1()调用时,已经和funObj.fun1没有任何关系了,其默认是通过window.funFromObj1()调用函数,故this指向window。
而对于箭头函数,由于其声明时就确定了其this指向,图二中箭头函数在window中声明,故无论是通过funObj.fun2()调用还是通过用funFromObj2接收一下funObj.fun2再进行调用,其this都是指向window的。大家可以想一下:怎么让funObj.fun2中的this指向funObj呢?
以上为我通过内存存储数据的角度分析this的指向性,若理解有误,请及时指正,多谢!!!
欢迎转载,务必注明出处。
参考链接:JavaScript 的 this 原理 MDN