说到this,入前端坑的人都知道这是JS初期语言毕竟之路。很多人(我就是)对于this的了解很模糊,或者不够全面。最近打算在反过来在看下es6,在es6中又出现了箭头函数对于this的理解有多了层认识。所以就在写一遍来加强自己的认知。
在讲this之前,我们先把作用域链在复习一下
在红宝书中对作用域链的描述有这么一句话:当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问简单来说,作用域链的作用就是在函数使用一个变量的时候,由近到远的查找有自身内部想最顶层也就是window的作用域中查找。
我们作用域链明白了,我们讲一下this.
this又分传统this和箭头函数中的this
传统this的指向:
1.this总是指向它的直接调用者。
2.在非严格模式下当没有调用者的时候,默认指向最顶层也就是window
3.在严格模式下('use strict')当没有调用者的时候,this就是undefined
4.在call、apply、bind绑定的时候,默认指向绑定的对象
箭头函数中this的指向:
1.箭头函数自身不包含this,它是继承与他所处的宿主对象的this。
光写概念,不说看得烦,我敲得也烦。直接上代码吧。
实例一:this指向它的直接调用者
var myObj = {
myVal : 3,
myFnc : function(){
console.log(this);
}
}
myObj.myFnc();//myobj
此时myObj调用了所以this指向于myObj;
实例二:非严格模式下没有调用者的时候
function myFnc(){
console.log(this);
}
myFnc();//window
此时,因为没有调用者,所以this默认指向最顶层也就是window
实例三:严格模式下没有调用者的时候
function myFnc(){
'use strict'
console.log(this);
}
myFnc() //undefined
此时,没有调用者,又因为当前是严格模式所以打印出来的this是undefined
实例四:call、apply、bind绑定的时候function myFnc1(){
function myFuc1(){
console.log(this);
}
function myFnc2(a,b){
console.log(this);
}
myFnc2.call(myFnc1);//myFnc1
此时绑定的就是myFnc1,所以当前this的指向就是myFnc1;
call和apply的绑定机制大致是一样的,所以就不一一解释了。
var myObj = {
myFnc :function(){
setTimtout(function(){
console.log(this);
}.bind(this))
}
}
myObj.myFnc();//myObj
因为在定时器函数中,没有调用者,所以默认指向window。又因为使用bind()方法给回调函数直接绑定了当前this指向,所以当前this指向就是myObj。
是不是感觉这么写很麻烦,当今的ES6的年代,还用啥bind绑定。如果需要返回当前函数伸手就是一个箭头函数
实例五:箭头函数简易版
var myObj = {
myFnc :function(){
setTimeout(() => {
console.log(this)
})
}
}
myObj.myFnc();
因为箭头函数继承的是它的宿主对象的this,也就是继承的myFnc的this,而myFnc的This指向是myObj,所以打印出来的当前this指向就是myObj;
实例六:箭头函数嵌套版
var myObj = {
myFnc :function(){
function childFnc(){
setTimeout(() => {
console.log(this)
})
}
childFnc();
}
}
myObj.myFnc();
小小的思考一下。。。
如果你一瞬间就明白的话,那就表明你已经通关了。
由里到外的分析,你就会发现很简单。
因为箭头函数,当前this继承于它的宿主也就是childFnc。childFnc方法的执行,因为没有调用者。所以它的this指向的是window。所以当前打印的this指向就是window。
总结:
this指向简单的说就是谁调用就指向谁,没调用就指向window(严格模式undefined)
当出现箭头函数内的,就指向宿主元素。