JavaScript那些事儿-容易迷失方向的this
在上一篇博文《JavaScript那些事儿-高大不好上的闭包》撸主对闭包做了概述,当然闭包这个东西理解是有一个过程的,也许在一个瞬间,某个转身突然就悟到了,有种“只可意会不可言传”的感觉;撸主天生愚钝,也是在这个理解的路上,不敢说自己写得有多好,但是将自己的理解说出来了,有说得不好的请博友踊跃指正!撸主洗耳恭听。
序
在我们开发实际项目上this的作用极大,它也更灵活的增加编程的乐趣,撸主在此对使用this的场景一一概述,其实在最开始接触JavaScript时,一直感觉它挺神秘,只到通过大大小小的项目总结出this其实并不是传说中的那么神秘,本文将一步一步解开它神秘的面纱(很高级的说)。
示例1:
function fn(){ console.log(this); } fn();
请问这段代码执行,this是谁?答案:window。
示例2:
var obj = { fn : function (){ console.log(this); } } obj.fn();
请问这段代码执行,this是谁?答案:obj。
示例3:
var oDiv = document.getElementById('div'); oDiv.onclick = function(){ console.log(this); };
请问当点击id为div的元素,this是谁?答案:oDiv。
示例4:
;(function () { console.log(this); })();
请问这个自执行函数执行时,this是谁?答案:window。
为什么能够一眼看出来this是谁,其实是有绝招的,其绝招是:函数执行的主体是谁,那么this就是谁。这句话似乎好高深,那么我将它更通俗表达,它遵循函数调用:看它的调用语句前有没有点儿(”.”),如果有点儿(“.”)那么this就是点儿(“.”)前面的东西,如果没有点儿(“.”)那么this就是window,这是第一条理论;对于事件绑定,在事件触发时this就是绑定的那个DOM元素,这是第二条理论。只要固执得遵循这两条理论,那么this问题走遍天下都不怕(当年读书流行这句话:学好数理化走遍天下都不怕),其实这两大理论一出,今天的博文就可以收尾了,但是很少有人遵循它,因为现实的诱惑实在太多,它无不诱惑着你让你不遵循这两条理论,就好像每天接到各种电话问你需不需要办理XX保险,XX理财,XX免费领取…都是诱惑你,其本质就是骗你钱。
(研究this好久了也没整明白,却被一个高手轻而易举解决了)
我们来分析一下上面4个示例,因为两个理论的重要思想已提出(我TM搞得跟党的两个理论三个代表似的),就不一一画图了:
对于示例1:第4行代码是它的调用语句,我们发现它的调用语句前没有点儿(“.”),根据第一条理论,this就是window;
对于示例2:第6行代码是它的调用语句,我们发现它的调用语句前有点儿(”.”),根据第一条理论,this就是点儿(”.”)前面的东西,故this是obj;
对于示例3:从第2~4行代码,我们将一个匿名函数绑定给oDiv这个DOM元素事件属性onclick上了,那么当事件触发,这个匿名函数执行时,这个this就是绑定的那个DOM元素即oDiv,显然遵循第二条理论;
对于示例4:这个是一个自执行函数,在执行时没有点儿(“.”),根据第一条理论,this就是window。(其实对于这种自执行函数this就是window,这个稍稍特殊)
常见的坑儿
第一个坑儿:
function fn2(){ console.log(this); } function fn(){ fn2(); console.log(this); } fn();
请问fn2被调用在执行时this是谁?fn被调用在执行时this是谁?那么我告诉你:fn2被调用执行时this是window,fn被调用执行时this也是window。显然都是根据理论一,得出的结论,究其原因:调用语句前有没有点儿(“.”),显然都没有点儿,即都是window。如果仍有不明白之处,请仔细斟酌红色标记的话。
第二个坑儿:
var oDiv = document.getElementById('div'); oDiv.onclick = (function(){ console.log(this); return function(){ console.log(this); }; })();
请问自执行函数((function (){ … })())中this是谁?当id为div的元素被点击时(其实就是执行的那个小函数)this又是谁?我们来分析下:这种自执行函数被调用执行时,其this就是window,这个在示例4中已提到,故自执行函数被调用执行时this就是window。我再啰嗦下,其实当我们的代码从上到下执行后(并不是点击id为div的元素后),这个自执行函数已经执行了,它执行返回的值就是里面的小函数(function(){ console.log(this); }),如果您有疑问,这里有图有真相:
我们知道这个id为div的元素的事件属性(onclick)的值是这个小函数,根据第二条理论我们就知道this就是oDiv。其实细心的你们会发现,当你点击id为div的D元素时,是不是相当于oDiv.onclick(),根据第一条理论,调用语句前有没有点儿(“.”),有点儿(“.”)那么this就是点儿(“.”)前面的东西,故也是oDiv。细心的你是不是也发现了!
总结
本篇博文准备多写几个坑儿,但是考虑到后面坑儿的知识点儿综合性比较强,当然对于大神请无视,比如function中的call和apply、JavaScript数据类型间比较等顾虑,当然这些知识点儿撸主在后面的文章中会一一概述,敬请大家关注!如有疑问或者说得不对的地方请指正。再次感谢大家的支持!