当前位置: 首页 > Web前端 > JavaScript

这个,你是谁?--javascript

时间:2023-03-27 10:03:10 JavaScript

这是javascript前端编程中非常常用的关键字,也是一道常见的面试题。但是由于这不是其他面向对象语言的定点,而是不同的调用代码,会产生不同的点。这。下面我们系统地分析一下我们在编程的时候在各个案例中是如何理解this点的。这个的定义首先,当我们面对一个编程语言的问题,尤其是关键字或者nativeAPI的时候,第一反应应该是查看官方文档,因为官方文档是最正确、最权威、最通俗的解释,这就是也是我这么多年编程经验的总结。下面是MDNWeb文档中对此的解释。与其他语言相比,函数的this关键字在JavaScript中的行为略有不同,严格模式和非严格模式之间也存在一些差异。在大多数情况下,函数的调用方式决定了this(运行时绑定)的值。this在执行过程中不能赋值,每次调用函数时this的值可能都不一样。ES5引入了bind方法来设置函数的this值,而不管函数是如何调用的。ES2015引入了箭头函数,它不提供自己的this绑定(this的值将保留封闭词法上下文的值)。最重要的一句话是,“调用函数的方式决定了this(runtimebinding)的值”,我们可以这样理解,比如调用person.run()时,run方法中的this指向person目的。在下一章中,我们将结合具体案例进行详细分析。(以下案例参考非严格模式的案例分析)this的案例分析我们将用6个案例来分析每个场景下this的含义Case1函数执行functionrun(){console.log('this->'+this)}run()//this->[objectWindow]console.log('this->'+this)//this->[objectWindow]vartitle='window'functiondoJob(){lettitle='doJob'functiontest(){console.log('this->'+this.title)//this->window}test()}doJob()第一个是运行时打印this对象,由于没有指定run的执行对象,所以默认this指向window。二是在全局环境中打印this,这也是默认的window对象。第三点是看测试的执行情况。测试是单独执行的,没有任何绑定对象,所以测试中的this是window对象Case2对象创建函数run(){this.sum=18console.log('this->'+this)}newrun()//this->[objectObject]letperson={name:'123',prun:run};person.prun()//this->[objectObject]letarr=[1,2,run]arr[2]()//this->1,2,functionrun(){...}注意:new在执行过程中会做四件事来创建一个新的子对象;让子对象继承其原型对象(prototype)构造函数;调用构造函数,将this指向子对象,并为子对象添加相应的属性(比如在run中添加this.sum=18);将子对象返回到函数外部。当第一个newrun()执行时,可以理解为new转run进入构造函数。这时候this会指向新创建的子对象,打印//this[objectObject]的结果。第二个人.run()执行时,this指向'.'前面的person对象,所以this指向person。当执行第三个arr[2]()时,this指向arr数组。Case3调用、申请、绑定应用函数run(){console.log('this->'+this)}letobj={name:'456'}run.call(obj)//this->[objectObject]run.apply(obj)//this->[objectObject]letbindRun=run.bind(obj)bindRun()//this->[objectObject]函数调用、apply、bind具有指定this的作用影响函数执行范围的对象。所以上面都是打印指定的obj对象。案例4dom绑定button...functionclickFun(){console.log('this->'+this)//this->[objectWindow]}中dom元素绑定事件,this指向window对象。Case5箭头函数letarrow=()=>{console.log('this->'+this)//this->[objectWindow]}arrow()vartitle='window'functiontest(){lettitle='test'console.log('testthis->'+this.title)//testthis->pletarrow1=()=>{console.log('arrow1this->'+this.title)//arrow1this->p}arrow1()setTimeout(()=>{console.log('setTimeoutthis->'+this.title)//setTimeoutthis->p});}letp={title:'p',test}p.test()vartitle='window'letobj={title:'obj',fun:()=>{console.log('this->'+this.title)//this->window},getTitle(){setTimeout(()=>{console.log('this->'+this.title)//this->obj});}}obj.fun()obj.getTitle()首先,箭头函数没有this指针,它的this指向上层作用域内的this。第一个执行arrow()函数时,由于箭头函数没有this指针,所以this指向上层窗口;在执行第二个arrow1和setTimeout中的箭头函数的时候,this跟在测试函数的this点后面,测试执行的时候前面有一个p对象,所以这里面的三个this都是指向p对象的,所以都是打印页第三,我们先分析obj.fun()的执行。由于fun函数是箭头函数,this指向前面的this,上层指的是全局窗口,不是obj,因为对象没有作用域。这是一个混淆点。然后在后面的setTimeout中,this指向getTitle函数的this,因为getTitle在'.'之前有obj,所以这里的this指向objCase6Prototype对象函数functionStudent(name){this.name=name}Student.prototype.logName=function(){console.log(this.name);}letxiaoqiang=newStudent('xiaoqiang')letdawang=newStudent('dawang')xiaoqiang.logName()//xiaoqiangdawang.logName()//dawang原型对象方法中,在执行过程中,this指向调用该方法的子对象,所以小强和大王调用时,会打印出各自的名字,同样遵循this指向的一个原则,看调用.总结一下这个的指向看定义,看调用。默认指向窗口;当函数被调用时,this通常指向调用该函数的对象,例如当obj.创建的对象;在dom事件中使用call、apply、bind自定义thisthis的指向对象,指向文档的window对象箭头函数没有独立的this,this指向上层的this对象;在原型对象this的共享方法中,this指向'.'的子对象。将来会调用这个方法