在开始今天的课程之前,让我得出一个结论,JavaScript中的this并不难,但非常容易掌握。先看一段代码:letfrom='武汉';varobj={from:'北京',logFrom:function(){console.log(from);}};letlogFrom=obj.logFrom;logFrom();obj.logFrom();执行以上代码,打印结果为:打印结果为WuHan,本例主要混淆的是from的以下两个定义,第一个属于全局变量,第二个属于局部变量,logFrom函数是否为在obj对象中使用全局from或from。答案是“使用全局from”。那么如果想使用obj对象内部定义的from怎么办呢?这就需要进入我们今天要讨论的话题,“这个机制”。让读者深感困扰的是,这代表了谁。记住这句话“这总是代表一个对象”。替换上述代码时(将打印语句console.log(from)替换为console.log(this.from)):varobj={from:'北京',logFrom:function(){console.log(this.from);}};执行时:letlogFrom=obj.logFrom;logFrom();执行结果未定义。执行时:obj.logFrom();执行结果为北京。为什么会这样?实际上,这是一个“动态”绑定到执行上下文的属性,这意味着在构建执行上下文时,绑定了一个this属性。执行上下文主要有两种:全局执行上下文和函数执行上下文,那么this有两种,一种是全局执行上下文中的this,一种是函数执行上下文中的this。(1)函数全局执行时(通过括号执行),this指向全局对象。在浏览器中,如果this在严格模式下未定义,则这是非严格模式下的窗口。比如设logFrom=obj.logFrom,此时变量logFrom是一个全局变量,全局调用一个函数,这个是window(这里属于非严格模式),window没有from属性,所以结果未定义。这里有一个问题供你思考。如果把第一行代码中的let换成var,会是什么结果呢?(2)通过对象调用方法时,this为当前对象。比如logFrom这个方法是通过obj调用的,this是obj,所以打印出来的结果就是BeiJing。使用1和2这两项可以解决大部分问题,但有一种情况需要注意。比如下面的代码:letlefex={name:'suyan',age:0,addAge:function(){console.log('outerthis=',this);this.age+=2;setTimeout(function(){console.log('innerthis=',this);this.age+=1;},100);}};lefex.addAge();打印结果为(非严格模式下执行):原来这两个this不一样,Innerfunctions没有从outerfunctions继承this。为了解决这个问题,出现了letthat=this这样丑陋的代码。当然可以使用箭头函数来解决这个问题:this指向当前创建的对象,下面代码中的this指向suyan。functionPerson(name){this.name=name;console.log(this);}letsuyan=newPerson('suyan');关于this的一个广泛使用的话题是如何改变this的方向,比如lefex对象中的方法addAge中的this是否可以是另一个对象?它将在下一节中讨论。大家来吧。
