各位看官,樓主開始說過寫幾篇部落格,這是這個系列的最後一集。吾以為:瞭解JavaScript的身世之謎,掌握其近乎心想事成的變數系統,瞭解其解析執行的偷樑換柱之法,熟悉布大師迂迴曲折的OOP實現。那你離height level也不遠了。當然,要想height level還要再掌握兩個常常被各位園友掛在嘴邊的東西:this與閉包。this是什麼鬼?閉包又是什麼鬼?照本宣科的概念,這裡不說,我們只聊“因為所以”。廢話少說,開聊!
this是什麼鬼?
this這玩兒稱呼為鬼一點不為過,好多小白一看滿屏都是this的指令碼瞬間眩暈。看樣子有點像Java、C#之類的this,但憑直覺好像又超越了Java、C#的this,看得是隱隱約約、似懂非懂。各種度娘、G哥大部分得到的都是照本宣科的解析。用心的會記下並研究的,無心的大大咧咧過目而已。於是乎,好多老鳥都沒徹底搞清楚this是什麼鬼。要想了解this是什麼鬼,那得先了解這鬼是怎麼來的。
話說JavaScript的設計初衷是過程式的,後面布大師為了緊跟時代潮流,迂迴曲折地實現OOP,為此引入了this來表示例項物件。OOP是實現,但是JavaScript的世界從此多了一個this。this在應用於JavaScript的OOP時候,表示的是例項本身。但是如果我寫的JavaScript並不需要new物件,而是隨意到處寫了this,那這個時候this代表什麼?真所謂填一坑挖一坑啊!有坑得填啊,於是,布大師又想摺子給這個this賦予意義了:當this應用於OOP的時候,它表示例項本身;而當this應用於非OOP的時候則表示this所在元素的歸屬物件。這話說來說去還是有點抽象,看程式碼最實在:
1)當this在function中,但是funciton只是過程式函式
<script> /**解析: *test在這裡只是個過程式的函式,沒有玩OOP *呼叫test函式列印this,那這裡的this指的就是test函式的歸屬 *而test函式是歸屬到當前Window物件上的 * ****/ function test(){ console.log(this); //結果是 Window物件 } test(); </script>
2)當this在某個非例項化的物件中
<script> /**解析: *這裡的this被定義一個名為f的函式中 *f函式歸屬的是obj物件 *結果:this代表obj物件 * ****/ var obj={ a:123, f:function(){ console.log(this);//結果 是obj物件 console.log(this.a);//結果是123 } }; console.log(obj.f());//結果 </script>
3)當this應用於OOP的玩法中
<script> /**解析: *clazz是一個類的建構函式,用於建立clazz的例項物件 *this在這裡就表示每一個new出來的物件 * ****/ function clazz(a,b){ this.a=a; this.b=b; this.print=function(){ console.log(this.a+this.b); }; } var c1=new clazz(1,1); c1.print(); //列印:2 var c2=new clazz(2,2); c1.print(); //列印:4 </script>
4)當this被偷樑換柱
<script> /**解析: *利用call或者apply讓f函式執行期間的this指向另一個物件 * ****/ var obj={ a:123, f:function(){ console.log(this);//結果 是obj物件 console.log(this.a);//結果是 undefined } }; //利用call或者apply讓f函式執行期間,將this換成當前window obj.f.call(this); </script>
閉包是什麼鬼?
我們們還是廢話少說,按套路,先了解這個所謂的閉包是怎麼來的。全世界(寫程式碼的人)都知道,像c、java、c++這些言語都有一套一套嚴格的語法,特別像資料型別、函式的定義都有自己規則,不是你想怎麼寫就寫的。但是JavaScript這玩兒,被布大師設計得你想怎麼寫就怎麼寫,竟然可以函式裡面再定義函式,可見自由度之大。你再看看java、c++能這樣幹嘛?自由是自由了,但是這玩法引出了一個問題:但凡大學裡認真念過點書的鞋同都知道,函式是基於棧執行的,如果函式巢狀函式,子函式又引用了父函式裡定義的成員,當父函式已經over的時候,按常規套路,父函式出棧了,它定義的成員也應該被Over了,如果此時子函式還活著,那它引用的父函式變數又不見了,那子函式就沒法用了。於是乎,布大師又不得不給這個bug做補丁,閉包這玩兒就出生了。那我們們通俗給閉包來個定義吧:
閉包:活著的人從死去的人那裡偷來了東西,讓那些東西不隨死去的人而消失。活著的人擁有了這些東西,這些東西的壽命也因此邊長了。這是JavaScript為了應對天馬行空的自由度產生的bug而打的補丁!
這比如雖然有點不雅,但也只是為了看官便於理解,請勿介意。好,我們們還是看看程式碼分析:
<script> function oldMan(){ var money=999999;// 老人的財富 //老人有一個年輕的兒子 return function young(){ console.log("兒子要花老子的錢"+money+"美刀"); } } var y=oldMan();//老人將兒子放出來之後就掛了,oldMan函式執行完成,出棧了!! y();//兒子開始活動了,兒子竟然有老人的錢 </script>
看官,不知道你看了這寥寥幾十字的通俗解法,是否還對那個所謂的閉包還懷抱敬畏呢!
如果你認真看這寥寥幾篇的通俗博文,我相信你對JavaScript的認識肯定是另一個階梯。當然要想在前端立足,僅僅掌握JavaScript還不足以混飯,你還得懂HTML、CSS。樓主打算接下來就這兩個知識再聊上幾篇。如有興趣,請留意!其他JavaScript的問題,也歡迎一起學習探討!