浅谈JavaScript中this的指向问题
JavaScript中this指向问题
记得初学JavaScript时,其中this的指向问题曾让我头疼不已,我还曾私自将其与闭包、原型(原型链)并称JS武林中的三大魔头。如果你要想在JS武林中称霸一方,必须将这三大魔头击倒。个人认为在这三大魔头中,this指向问题的武功最菜(难度最低)。俗话说柿子捡软的捏,那我们就先从this指向问题下手。
先记住攻克this指向问题的口诀(前辈们的总结):哪个对象调用函数,函数里的this就默认指向哪个对象(注意this只能指向对象)。这里说“默认指向”是因为我们通过箭头函数、call、apply、bind等手段来改变this的指向。现在我们只讨论this的默认指向。
全局作用域下以及全局作用域的函数中,this默认指向全局对象window
在严格模式下,全局作用域的函数中,this默认指向undefined,这是严格模式所规定的。
//非严格模式下 console.log(this);//Window functiondoSomething(){ console.log(this);//Window } doSomething();//这里可以看成window.doSomething(),所以函数里的this指向全局对象window //严格模式下 'usestrict'; console.log(this);//Window functiondoInStrict(){ console.log(this);//undefined } doInStrict();
对象里的函数,this指向该对象
vara=1; varobj={ a:2, fn:function(){ console.log(this);//{a:2,fn:ƒ} console.log(this.a);//2 } }; obj.fn();
上面函数被调用后,从打印结果可以看出此时this指向的是调用函数的对象obj。如果将对象中的函数赋给全局对象中定义的变量fn1,执行fn1又会出现什么结果呢?
vara=1; varobj={ a:2, fn:function(){ console.log(this);//Winidow console.log(this.a);//1 } }; varfn1=obj.fn; fn1();//可以看成window.fn1();
从上面的例子可以看出,fn1与obj.fn指向的函数是相同的,但是调用它的对象不同,那么函数中this的指向也就不一样了。
再看一个比较复杂的例子:
vara=0; functionfn(){ consoloe.log(this.a); } varobj1={ a:1, fn:function(){ console.log(this.a); } }; varobj2={ a:2, fn:function(){ fn(); obj1.fn(); console.log(this.a); } } obj2.fn();
先说下执行结果,分别打印012。当obj2调用fn函数时,先执行的是fn(),这个函数是在全局作用域中定义的,该调用可以看成window.fn(),所以,该函数内部的this指向的是window全局对象,this.a自然就是全局对象中的a值(0)。
接着执行的是obj1.fn(),它会从obj1中找到fn函数并执行。obj1中的函数fn执行时调用它的对象是obj1,所以,此时函数内部的this指向的就是obj1自身。那么this.a查到的值也就是对象obj1中a的值(1)。
最后打印函数中this所处的函数fn是被obj2调用的,那么自然而然this就指向了obj2,所以this.a的结果就是2了。
从上面这个例子我们可以看出:函数内部this指向跟调用函数的对象有关,跟函数在哪里调用没有关系。
Window内置函数的回调函数中,this指向Window对象。
window的内置函数(setIntervalsetTimeout等),其回调函数中的this指向的是window对象。
varname='window'; varobj={ name:'obj', func:function(){ setTimeout(function(){ console.log(this.name)//window },1000) } } obj.func()
但是一般在开发中,很多场景都需要改变this的指向。请参考JS中this指向的更改,这里就不再赘述了。
this既不指向函数自身也不指向函数的词法作用域,this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。
找到函数直接调用的位置后用下面的几条规则就可以判断出this的绑定对象。
- 由new调用?绑定到新创建的实例对象上。
- 由call、apply、bind调用?绑定到指定的对象上。
- 由上下文对象调用?绑定到那个上下文对象上。
- 默认:在严格模式下绑定到undefined,否则绑定到全局对象Window上。
- ES6中的箭头函数会继承外层函数调用的this绑定,这和varself=this;的绑定机制一样。
到此这篇关于浅谈JavaScript中this的指向问题的文章就介绍到这了,更多相关JavaScript中this指向问题内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!