前天去面試,有個gg問了一些js知識,其中有一道call與apply用法的題目,儘管在365天前用過call方法,但當時還是沒能答上來,今天深入總結一下
call和apply,它們的作用都是將函數綁定到另一個物件上去運行
兩者的格式與參數定義:
call( thisArg [,arg1,arg2,… ] ); // 參數列表,arg1,arg2,...apply(thisArg 🎜>
上面兩個函數內部的this指針,都會被賦值為thisArg,這可實現將函數作為另外一個對象的方法運行的目的
首先,我們先看個簡單的例子(call):
然後,運行結果如下:
global var
global var
member var
input text
func
member var
input text
func
最後,分析結果
2、函數gFunc呼叫call方法,
this預設指向第一個參數window物件,因此this.value也為global var
3、函數gFunc呼叫call方法,this預設指向第一個參數new mFunc(),即mFunc的物件,因此this.value為mFunc的成員變數member var
4、函數gFunc呼叫call方法,this預設指向第一個參數input text控件,即id='idTxt'的控件,因此this.value為input控件的value值 input text
5、函數func2呼叫call方法,this預設指向第一個參數func函數物件,因此this.value為this.a,即func
6、函數func2呼叫call方法,第二個參數屬於函數物件func2的參數,因此alert(x)為第二個參數func2
二、call 繼承用法與改良
js使用call模擬繼承
複製程式碼 程式碼如下:
,但實際輸出卻是
baseB 成員和baseB 成員
(已在IE9、8、6,Maxthon、Chrome、FF、Opera、Safari、360等瀏覽器測試過,結果皆為:baseB會員)
至此,機器是不會錯的,這就需要我們深入分析
為了取得實物,我們藉助chrome瀏覽器的調試工具,下斷點,進行調試,結果發現:
當呼叫
extend.showSelfA();時,此時的this指向extendAB(不是我們推測的兩次都指向baseB物件)
真實原因是extendAB物件的成員變數成員在被baseB.call(this);
實例化時,被baseB的成員成員覆蓋了,即extendAB的成員成員由baseA成員賦值為baseB member當然,我們也可以對上面的baseA程式碼稍作修改,來驗證我們偵錯分析的正確性:
複製程式碼 程式碼如下:
function baseA() // 基類A{ this.memberA = "baseA member"; // 成員改成memberA,以區分BbaseBbase"; // 成員改成memberA,區分BbaseB的member this.showSelfA = function() { window.alert(this.memberA); //顯示memberA
}}
程式碼如下: