Javascript 一些筆記, this指標, apply, call以及 prototype
this指標
this通常有4種情況
- new關鍵字
- JSON object
- 呼叫call, apply, bind
- 默認綁定
在一般情形下,this會默認指向window。但在創建新的物件的同時,如用new關鍵字或是用JSON object產生物件時,新建的object會產生新的scope,而this會指向那個新的scope。
最後是呼叫call, apply和bind所指定綁上去的物件。如以下第14行,雖然 f()等於A物件的func函數,但因為沒有產生新的物件,因此會以當前f()所在的scope默認綁上去一個this,也就是window。
所有javascript的function的this所指向的地方皆為執行階段所在的scope,而不是宣告該函數的位置,而scope只有在新的物件被創建時才會產生,如this和json object。
因此可以看到12行的a由new產生一個scope,14行默認綁定window,19行綁定JSON object,21行直接呼叫19行的scope。
Prototype.Call(), Apply(), Bind(),它可以讓你直接把this綁定到其他物件的scope。
這是一個很常見的函數,他們的功用就是讓某個韓式以不同物件的scope執行,而他們三者的不同在於Call吃個別多個參數,apply吃array,bind則是有別於他們兩者,他會永久綁定某個scope。
以下是一個很有趣的應用,HTMLCollection並沒有像是array一樣有這麼多好用的方法可以呼叫,我們就從一個空array裡借用它的方法,把map()這個方法的scope綁到HTMLCollection上。
prototype,它可以讓你對某個物件添加它原來沒有的功能,甚至是達到物件導向的繼承功能。
這邊第11行Lamborghini在constructor內直接用call去叫Car的constructor,因此Lambo也會獲得所有Car的property。之後在15行把Car的prototype鏈也複製給Lambo,要注意的是17行,因為整個prototype鏈都是從Car那邊拿來的,本質上new 一個Lambo雖然會近Lambo的constructor,但會在裡面再叫Car的constructor,因此返回的是一個Car的instance而不是Lambo。因此最後要把Lambo的constructor設回Lamborghini(奇妙吧XD)。
第5行為Car增加了一個run方法,這邊要注意的是,很多新手分不出來用prototype跟直接用this寫一個方法有什麼差別,認為這兩者是相同的,但實際上this是在每次經由constructor建立一個物件以後,才把某個property或是方法加到物件中,而prototype是把property加到prototype鏈裡面。
範例如下:
執行12行到25行會發現,prototype.run並沒有辦法覆寫原本的函數,原因是雖然prototype鏈上確實有run()這個function,但是在每次new一個函數之後,就會被constructor內的this.run()給覆蓋過去,因此用new 產生出來的物件都無法叫到prototype.run()。
Prototype甚至可以當作middleware
例如你想在某個函數每次執行前,都先執行某個功能,你可以先儲存那個function,然後用prototype複寫函數,最後利用apply把arguments傳進原本的函數
嗯… 因為我實在很懶,寫這樣一篇也花了我2小時,所以就先這樣吧。不專業JS心得文~