当前位置: 首页 > 科技观察

前端开发初学者一定要了解“this”关键字

时间:2023-03-14 08:43:06 科技观察

如果对JavaScript关键字this理解不够深入,有时会掉进意想不到的坑。在这里,我们总结了5条一般规则,以帮助您确定this实际指的是什么。虽然并未涵盖所有情况,但使用这些规则可以正确推断出大多数日常情况。this的值通常由函数的执行环境决定,也就是说取决于函数是如何被调用的;每次调用相同的函数时,this可能指向不同的对象;全局对象(GlobalObject)打开Chrome浏览器开发者面板(Windows:Ctrl+Shift+J)(Mac:Cmd+Option+J),输入:console.log(this);看看输出是什么?//Window{}窗口对象!因为它工作在全局域下,this指向全局对象。浏览器中的全局对象是窗口对象。为了让你更清楚地理解为什么this指向window对象,我们再看一个例子:varmyName='Brandon';我们可以通过在控制台输入myName来访问它的值:myName//output'Brandon'事实上,所有在全局定义的变量都绑定到window对象上。让我们做下面的测试:window.myName//output'Brandon'window.myName===myName//outputtrue现在我们把它放在函数里面看看它有什么效果。functiontest(){returnthis;}test();你会发现this还是指向了全局的window对象。因为this关键字不在声明的对象内,所以它默认为全局window对象。这一点对于大多数初学者来说可能有点难以理解。看完这篇文章,你会豁然开朗。注意:如果在strcit模式下,这在上面的例子中是未定义的。声明对象(DeclaredObject)当this关键字用在声明对象内部时,它的值将绑定到调用this的函数的最近的父对象。让我们用一个例子来说明这个问题:varperson={first:'John',last:'Smith',full:function(){console.log(this.first+''+this.last);}};person。full();//Output'JohnSmith'在声明的对象person的full函数中使用了this,那么调用this的full函数的最近的父对象就是person,所以this指向person。为了更好的说明this实际上指向的是person对象,可以将下面的代码复制到浏览器控制台打印出来。varperson={first:'John',last:'Smith',full:function(){console.log(this);}};person.full();//输出对象{first:"John",last:"Smith",full:function}让我们看一个更复杂的例子:varperson={first:'John',last:'Smith',full:function(){console.log(this.first+''+this.last);},personTwo:{first:'Allison',last:'Jones',full:function(){console.log(this.first+''+this.last);}}};这里我们有嵌套的对象,这个时候this指向谁呢?我们打印出来看看:person.full();//output'JohnSmith'person.personTwo.full();//output'AllisonJones'你会发现满足了我们前面描述的规则:它的值将绑定到调用它的函数的最近父级。new关键字当使用new关键字构造新对象时,this将绑定到新对象上。让我们看一个例子:functionCar(make,model){this.make=make;this.model=model;};根据第一条规则,你可以推断this指向全局对象。但是如果我们使用new关键字声明一个新的变量,Car函数中的this会绑定一个新的空对象,然后初始化this.make和this.model的值。varmyCar=newCar('Ford','Escape');console.log(myCar);//输出Car{make:"Ford",model:"Escape"}调用,绑定,应用我们可以在call()中显示、bind()和apply()设置this的绑定对象。这三个函数非常相似,但我们需要注意它们的细微差别。看一个例子:functionadd(c,d){console.log(this.a+this.b+c+d);}add(3,4);//输出NaNadd函数输出NaN,因为this.athis.b未定义。现在我们引入对象,使用call()和apply()调用:functionadd(c,d){console.log(this.a+this.b+c+d);}varten={a:1,b:2};add.call(ten,3,4);//输出10add.apply(ten,[3,4]);//输出10当我们使用add.call()时,第一个参数就是This需要绑定到对象上,其余为add函数的原始参数。因此,this.a指向10.a,this.b指向10.b。add.apply()类似,只是第二个参数是一个数组,用来存放add函数的参数。bind()函数类似于call(),但bind()函数不会立即被调用。bind()函数返回一个函数并绑定它。下面我们通过一个例子来帮助理解bind()函数的应用场景:varsmall={a:1,go:function(b,c,d){console.log(this.a+b+c+d);}}varlarge={a:100}execute:small.go(2,3,4);//输出10如果我们要使用large.a的值而不是small.a呢?我们可以使用call/apply:small.go.call(large,2,3,4);//输出109但是不知道这三个参数应该传入什么值怎么办呢?我们可以使用bind:varbindTest=small.go.bind(large,2);如果我们在控制台打印出bindTest,我们会看到:console.log(bindTest);//Outputfunction(b,c,d){console.log(this.a+b+c+d);}注意:该函数已经将this绑定到大对象上,并传入了第一个参数b。因此,接下来我们需要传入剩下的参数:bindTest(3,4);//输出109箭头函数(->)因为太占篇幅了,我们会写一篇博客来介绍。结论当您读完这篇博文后,您应该能够理解this在大多数情况下指的是什么。接下来总结一下:this的取值通常是由当前函数的执行环境决定的;在全局范围内,this指向全局对象(window对象);当使用new关键字声明时,this指向新创建的对象;我们可以使用call()、bind()、apply()来设置它;箭头函数不会绑定这个。【本文为专栏作家“谢军”原创稿件。转载可通过作者微信取得联系公众号(jingfeng18)】点此查看该作者更多好文