js裡函式呼叫的四種模式
js 裡函式呼叫有4種模式:方法呼叫、正常函式呼叫、構造器函式呼叫、apply/call
呼叫。同時,無論哪種函式呼叫除了你宣告時定義的形參外,還會自動新增2個形參,分別是this
和 arguments
。
1.方法呼叫
這個很好理解,函式是一個物件的屬性,比如
var a = {
v : 0,
f : function(xx) {
this.v = xx;
}
}
a.f(5);
這個時候,上面函式裡的 this
就繫結的是這個物件 a
。所以this.v
可以取到物件a
的屬性 v
。
2.正常函式呼叫:
依然看程式碼
function f(xx) {
this.x = xx;
}
f(5);
這個時候,函式 f
裡的this
繫結的是全域性物件,如果是在瀏覽器執行的直譯器中,一般來說是樓上說的 window
物件。所以這裡 this.x
訪問的其實是 window.x
,當然,如果 window
沒有 x
屬性,那麼你這麼一寫,按照 js 的坑爹語法,就是給 window
物件新增了一個 x 屬性,同時賦值。
3.構造器函式呼叫:
建構函式一直是我認為是 js 裡最坑爹的部分,因為它和 js 最初設計的基於原型的物件導向實現方式格格不入,就好像是特意為了迎合大家已經被其他基於類的面相物件實現給慣壞了的習慣。
如果你在一個函式前面帶上 new
關鍵字來呼叫,那麼 js 會建立一個prototype
屬性是此函式的一個新物件,同時在呼叫這個函式的時候,把this
繫結到這個新物件上。當然new
關鍵字也會改變return
語句的行為。看程式碼
function a(xx) {
this.m = xx;
}
var b = new a(5);
上面這個函式和正常呼叫的函式寫法上沒什麼區別,只不過在呼叫的時候函式名前面加了關鍵字new
罷了,這麼一來,this
繫結的就不再是前面講到的全域性物件了,而是這裡說的建立的新物件,所以說這種方式其實很危險,因為光看函式,你不會知道這個函式到底是準備拿來當建構函式用的,還是一般函式用的,所以我們可以看到,在jslint
裡,它會要求你寫的所有建構函式,也就是一旦它發現你用了 new
關鍵字,那麼後面那個函式的首字母必須大寫,這樣通過函式首字母大寫的方式來區分,我個人只有一個看法:坑爹:)
4.apply/call 呼叫:
我們知道,在 js 裡,函式其實也是一個物件,那麼函式自然也可以擁有它自己的方法,有點繞,就好像函式可以自己有屬性也是一個函式。其中每個函式都擁有apply()
這個方法,讓我們構造一個引數陣列傳遞給函式,同時可以自己來設定this
的值,這就是它最強大的地方,上面的3種函式呼叫方法,你可以看到,this
都是自動繫結的,沒辦法由你來設,當你想設的時候,就可以用 apply()
了。apply
接收2個引數,第一個是將傳遞給這個函式的 this
的值,第二個是引數陣列。看程式碼:
function a(xx) {
this.b = xx;
}
var o = {};
a.apply(o, [5]);
alert(a.b); // undefined
alert(o.b); // 5
是不是很神奇,函式 a
居然可以給o
加屬性值。當然,如果你 apply
的第一個引數傳遞 null
,那麼在函式a
裡面 this
指標依然會繫結全域性物件。你可能要問了,apply
函式是哪來的,因為在 js 裡所有的函式都有一個共同的prototype
,也就是傳說中的 Function.prototype
, 這個原型裡有兩個神奇的方法,一個就是這裡的apply
,另一個就是讓題主疑惑的 call
。call()
方法和 apply()
方法很類似,它們的存在都是為了改變this
的繫結,那call()
和 apply()
有什麼區別呢?就我個人看來,沒啥鳥區別。。。開玩笑!剛剛說了,上面 apply()
接收兩個引數,第一個是你想要 this
繫結的物件,第二個是一個引數陣列,注意是一個陣列,你想傳遞給這個函式的所有內容都放在陣列裡,然後 apply()
函式會在傳遞形參時自動幫你展開,同時加入我上面提到的另一個神奇形參arguments
。而 call()
呢,它的第一個引數也是你想要this
繫結的物件,但是後面可以接受不定引數,而不再是一個陣列,也就是你可以像平時給函式傳參那樣把這些引數一個一個傳遞,當然,神奇形參 arguments
還是不會少的。所以如果一定要說有什麼區別的話,看起來是這樣的
function a(xx, yy) {
alert(xx, yy);
alert(this);
alert(arguments);
}
a.apply(null, [5, 55]);
a.call(null, 5, 55);
僅此而已。
相關文章
- JS的五種函式呼叫方式JS函式
- PostgreSQL函式裡呼叫函式(SETOF + RETURN QUERY)SQL函式
- JS中函式內套函式的呼叫JS函式
- 在JS中一個function函式要呼叫另一個函式裡的變數。JSFunction函式變數
- 幾種函式呼叫方式函式
- Js基礎知識4-函式的三種建立、四種呼叫(及關於new function()的解釋)JS函式Function
- js函式 函式自呼叫 返回函式的函式 (閉包)JS函式
- JS函式的定義與呼叫方法JS函式
- iframe裡面的頁面呼叫父視窗,左右視窗js函式的方法JS函式
- 函式呼叫的三種方式 __cdecl、__stdcall、__fastcall函式AST
- 函式組合的 N 種模式函式模式
- [譯] 理解JS的函式呼叫和‘this’的指向JS函式
- JS 建立例項物件的四種模式JS物件模式
- js函式使用的幾種方式JS函式
- 兩個JS之間的函式互相呼叫JS函式
- 建構函式,拷貝賦值函式的N種呼叫情況函式賦值
- 【翻譯】理解JS的函式呼叫和‘this’的指向JS函式
- Python透過函式名呼叫函式的幾種場景Python函式
- javascript 函式中的 this 的四種繫結形式JavaScript函式
- 詳解 JS 中 new 呼叫函式原理JS函式
- js實現的iframe呼叫父頁面函式JS函式
- JS中建立函式的幾種方式JS函式
- react中三種函式呼叫方法總結React函式
- 外部函式的呼叫函式
- STM32延時函式的四種方法函式
- 為什麼 Go 裡值為 nil 可以呼叫函式?Go函式
- java可以像python中的函式式工具裡的reduce那樣呼叫嗎?JavaPython函式
- JavaScript裡的函式JavaScript函式
- Javascript的函式呼叫與thisJavaScript函式
- 子函式呼叫函式
- 聊聊四種Oracle數字取整函式Oracle函式
- 在 js 裡定義按鈕的響應函式JS函式
- Rxjs 裡 subscribeToArray 工具函式的詳細分析JS函式
- js中的寫出想jquery中的函式一樣呼叫JSjQuery函式
- JavaScript中七種函式呼叫方式及對應 this 的含義JavaScript函式
- javascript忍者祕籍-第四章 理解函式呼叫JavaScript函式
- C 語言中返回字串函式的四種實現方法字串函式
- 在vue生命週期裡呼叫函式時犯的一個錯誤Vue函式