在JavaScript中一共有下面4種調用方式:
(1)?基本函數調用
(2)方法調用
(3)構造器調用
(4)通過call()和apply()進行調用
1.?基本函數調用
普通函數調用模式,如:
1 2 3 4 | ?? function ?fn(o){ ????? ……? ?? } ?? fn({x:1}); |
在基本函數調用中,
(1)每個參數作為實參傳遞給聲明函數時定義的形參;
(2)this被綁定到全局變量(直接調用一般指的是window)
1 2 3 4 5 6 7 8 9 10 | ?? var ?object?=?{value:1}; ?? var ?value?=?2; ? object.printProps?=? function (){ ???? var ?printValue?=? function (){ ?????? console.log( this .value); ???? }; ??? printValue(); ??? console.log( this .value); ? } ? object.printProps(); |
此時的運行結果是:
?2
?1
在printValue()函數在執行時,this.value值為2,也就是說,this指向的是全局對象,而不是對象object。
(3)返回值:函數的返回值成為調用表達式的值。
I.?如果函數返回是解釋器到達結尾,也就是沒有執行到return?XXX的語句。返回值為undefined。?
II.?如果函數返回是因為接受器執行到return?xxx語句,?返回return之后的值。?
III.?如果return語句后沒有值,即return,則返回undefined。
2.?方法調用
當一個函數被保存為對象的一個屬性時,稱為方法。
(1)參數和返回值的處理與函數調用一致;
(2)調用上下文this為該對象
1 2 3 4 5 6 7 8 9 10 11 | ? ?function ?print(){ ???? console.log( this .value);? ?? } ?? var ?value=1; ?? var ?object?=?{value:2}; ?? object.m?=?print; ?? //作為函數調用 ?? print(); ?? //作為方法調用 ?? object.m(); |
運行結果為:
?1
?2
當調用print時,this綁定的是全局對象,打印全局變量value值1。
但是當調用object.m()時,this綁定的是方法m所屬的對象Object,所以打印的值為Object.value,即2。
3.?構造器調用
?函數或方法調用之前帶有關鍵字new,它就構成構造函數調用。如:
1 2 | ? function ?fn(){……} ? var ?obj?=? new ?fn(); |
(1)參數處理:一般情況構造器參數處理和函數調用模式一致。但如果構造函數沒用形參,JavaScript構造函數調用語法是允許省略實參列表和圓括號的。
如:下面兩行代碼是等價的。
1 2 | ?? var ?obj?=? new ?Object(); ?? var ?obj?=? new ?Object; |
(2)函數的調用上下文為新創建的對象。
1 2 3 4 5 6 7 8 9 10 | ? function ?fn(value){ ??? this .value?=value; ? } ? var ?value?=1; ? var ?obj?=? new ?fn(2); ? console.log(value); ? console.log(obj.value); ? fn(3); ? console.log(value); ? console.log(obj.value); |
運行結果:
?1
?2
?3
?2
?I.?第一次調用fn()函數是作為構造函數調用的,此時調用上下文this被綁定到新創建的對象obj。所以全局變量value值不變,obj新增一個屬性value,值為2;
?II.?第二次調用fn()函數是作為普通函數調用的,此時調用上下為this被綁定到全局對象,在瀏覽器中為window。所以全局對象的value值改變為3,而obj的屬性值不變。
(3)構造函數通常不使用return關鍵字,返回值為新對象。而如果構造函數顯示地使用return語句返回一個對象,那么調用表達式值就為這個對象。如果構造函數使用return語句但沒有指定返回值或者返回一個原始值,則忽略返回值,同時使用新對象作為調用結果。
4.通過call()和apply()進行調用
雖然在一個獨立的函數調用中,根據是否是strict模式,this指向undefined或window,不過,我們還是可以控制this的指向的!要指定函數的this指向哪個對象,可以用函數本身的apply()或call()方法,它們都是接收兩個參數。
call()方法使用它自有的實參列表作為函數的實參,apply()方法要求以數組的形式傳入參數
apply方法第一個參數是改變后的調用對象,第二個參數是將函數參數以數組形式傳入[?],而call()第一個參數與call()方法相同,第二個參數是原來參數序列......。