在编程过程中,有同学遇到了ES6中this不清楚的问题。代码抽象如下:functionmyFunction(){varmthis=this;setTimeout(()=>{//this=mthisconsole.log('thisinsetTimeout:',this)},100)}这是什么,是全局上下文窗口吗?这里需要和ES5区分开来。ES6的箭头函数中没有this,this会作为一个变量向上层词法范围查找,直到找到为止。下面看看一些相关的知识函数调用functionmyFunction(a,b){returna*b;}myFunction(2,3)输出结果是6上面的myFunction函数不属于任何对象。但是在JavaScript中,总是有一种默认的全局对象。在HTML中,默认的全局对象是HTML页面本身,上述所有功能都“属于”HTML页面。在浏览器中,这个页面对象就是浏览器窗口。上面的函数自动变成了窗口函数。myFunction()和window.myFunction()是同一个函数。这是调用函数的常用方法,但这不是一个好习惯。全局变量、方法或函数很容易在全局对象中产生命名冲突和漏洞。this关键字在JavaScript中,称为this的东西指的是“拥有”当前代码的对象。当在函数中使用时,this的值是“拥有”该函数的对象。请注意,这不是一个变量。它属于关键词。您无法更改此值。全局对象作为调用函数的函数当一个对象在没有所有者对象的情况下被调用时,this的值就变成了全局对象。在网络浏览器中,全局对象是浏览器对象。此示例返回具有以下值的窗口对象:示例varx=myFunction();//x将成为窗口对象functionmyFunction(){returnthis;}将函数作为全局函数调用将导致this的值成为全局对象。使用窗口对象作为变量很容易使程序崩溃。将函数作为方法调用在JavaScript中,您可以将函数定义为对象方法。以下示例创建一个对象(myObject),它具有两个属性(firstName和lastName)和一个方法(fullName):.firstName+""+this.lastName;}}myObject.fullName();//将返回"BillGates"fullName方法是一个函数。函数属于对象。myObject是函数的所有者。称为this的东西是“拥有”这段JavaScript代码的对象。在本例中,this的值为myObject。有一个测试!修改fullName方法以返回this的值:示例varmyObject={firstName:"Bill",lastName:"Gates",fullName:function(){returnthis;}}myObject.fullName();//将返回[objectObject](ownerobject)作为对象方法来调用函数,this的值指向对象本身。通过构造函数调用函数如果函数调用前面有new关键字,那么它就是构造函数调用。看起来你创建了一个新函数,但由于JavaScript函数是对象,你实际上创建了一个新对象:示例//这是函数构造函数:functionmyFunction(arg1,arg2){this.firstName=arg1;this.lastName=arg2;}//创建了一个新对象:varx=newmyFunction("Bill","Gates");x.名字;//返回“Bill”构造函数调用创建了一个新对象。新对象从其构造函数继承属性和方法。构造函数中的this将指向调用函数时创建的新对象。setTimeout(1)ES5《javascript高级程序设计》说:“timeout调用的代码是在全局作用域执行的,所以函数中this的值在非严格模式下指向window对象,在严格模式下是undefined。”这里讨论非严格模式。es5中setTimeout的延迟执行函数中的this始终指向window。例如:functionmyFunction(){varid=1024;console.log('thisinmyFunction:',this,this.id)setTimeout(function(){//这里需要注意id和this.id是否相同this=windowconsole.log('thisinsetTimeout:',this,this.id,id)},100)}varmyobj={id:9528}varid=9527;myFunction(myobj)myFunction.call({id:1987})输出结果:myFunction(myobj)执行结果thisinmyFunction:Window9527setTimeoutthis:Window95271024myFunction.call({id:1987})执行结果myFunctionthis:Object{id:1987}1987thisinsetTimeout:Window95271024补充说明一般来说,this总是指向到调用该方法的对象,但是在使用call()和apply()方法时,this的指向会发生变化,this的指向会被转移。call.(object,arg1,arg2...)apply()和call()类似,只是apply的第二个参数必须传入数组,而call的第二个参数可以是任意类型。obj1.methodName.call(obj2,argument1,argument2)如上,call的作用是把obj1的方法放到obj2上使用,js中一切都是对象,函数就是对象,函数也可以调用一个方法,下面的argument1..这些作为参数传入。A.call(B,x,y):把A的函数放到B中运行,x和y是A方法的参数。使用call实现继承,使用this继承myfunc1中的所有方法和属性。(2)ES6在ES6中,在setTimeout中,如果执行了一个箭头函数,那么这个函数的this就指向了outercaller。函数myFunction(){varid=1024;console.log('thisinmyFunction:',this,this.id)setTimeout(()=>{//这里需要注意id和this.id是不同的this=callerofmyFunctionconsole.log('thisinsetTimeout:',this,this.id,id)},100)}varmyobj={id:9528}varid=9527;myFunction(myobj)myFunction.call({id:1987})输出结果:myFunction(myobj)执行结果thisinmyFunction:Window9527setTimeoutthis:Window95271024myFunction.call({id:1987})执行结果myFunctionthis:Object{id:1987}1987this:Object{id:1987}in1987setTimeout19871024ES6箭头函数this将用作变量来搜索上层词法范围,直到找到为止。所以这里箭头函数中的this,往上看就是myFunction函数的this,这里就是对象{id:1987}。下面是Babel转箭头函数生成的ES5代码,可以很清楚的说明this的方向。//ES6functionfoo(){setTimeout(()=>{console.log('id:',this.id);},100);}//ES5functionfoo(){var_this=this;setTimeout(function(){console.log('id:',_this.id);},100);}在上面的代码中,转换后的ES5版本清楚地表明箭头函数根本没有自己的this,而是指外层这个。除此之外,箭头函数中不存在以下三个变量,指向外层函数对应的变量:arguments、super、new.target。参考https://www.w3school.com.cn/js/js_function_call.aspJavaScript函数调用https://es6.ruanyifeng.com/?search=this&x=0&y=0#docs/function#%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E7%82%B9
