Javascript高階程式設計學習筆記(16)—— 引用型別(5) Function型別
JS中許多有趣的地方都和函式脫不了聯絡
那麼是什麼讓JS中的函式這麼有趣呢?
我們一起來看看吧
Function型別
在JS中函式實際上就是物件,每個函式都是Function型別的例項,和JS的其他引用型別都擁有屬性和方法
正是由於這個原因,函式名實際上就是一個指標,指向函式物件,並不會與函式繫結
函式的宣告
建立一個函式一般來說有下面幾種方法
// function關鍵字宣告 function sayHello(){ alert("hello"); } // 函式表示式 var sayHello = function(){ alert("hello"); } // 建構函式 var sayHello = new Function("alert('hello')");// 接收任意數量引數,最後一個引數為函式體
其中最少使用的就是最後一種,因為這種方式會導致JS解析兩次程式碼
而對於function 和 表示式這兩種方式來說,區別在於(在ES6以下)function宣告會在建立執行環境階段完成,而表示式會在程式碼執行階段建立函式;
簡單地說function宣告的函式會比,函式表示式更早的建立函式(在程式碼執行之前)
PS. 由於函式名僅僅只是指向函式的指標,所以一個函式可以有多個函式名
沒有過載
之前的文章中,我提到了JS的函式沒有過載
這一切的根源就是:JS中的函式名只是一個指標,而不是一個函式簽名
所以當我們在JS中宣告同名函式的時候,實際上就是讓已經指向一個函式的指標指向另外一個函式,自然也就不能實現過載了
變數提升
變數提升,以及閉包等概念,在許多公司前端面試的時候經常會考到
這裡撇開閉包不談,先來說一下變數提升
變數提升這一概念只存在於ES6以下的ES語法中
前面講JS執行環境的時候我詳細解釋了這一過程
什麼是變數提升?
說白了變數提升就是:當JS在執行到宣告變數的語句之前就可以訪問該變量了
對於函式之外的變數,變數提升雖然可以在宣告語句前訪問到該變數,但是由於賦值語句尚未執行,所以只能訪問到 undefined
在上方的例子中我們看到變數a就在宣告語句前被我們訪問了,而變數 b 我們沒有宣告所以js報錯
而對於函式來說,函式的變數提升,我們甚至可以在函式宣告前就訪問到函式的函式體
而變數提升的原理就是,JS的執行環境的建立,具體過程見下圖:
所以var宣告的變數在,語句執行前就已經被js引擎設定了值,而ES6的let,const在建立執行環境時並不會為這些變數設定值,所以也就不存在變數提升
而由於函式表示式是在程式碼執行階段才會執行,所以函式表示式建立的函式並不能在宣告語句前訪問
我也不知道我講清楚沒,沒懂的小夥伴可以留言,有錯的地方也歡迎大家留言指出
函式作為函式返回值
在JS中由於函式本就是一個物件,自然也可以作為函式的返回值返回
這種情況適用於使用的函式需要根據引數的型別、值等呼叫不同的函式的情況
函式內部屬性
函式的內部有兩個特殊的物件:
1.this
2.arguments
其中 this 物件指向的是當前函式的執行環境物件
而arguments用於儲存函式的引數
arguments物件有個callee屬性,指向當前函式本身
通過arguments可以實現更加安全的遞迴呼叫
var test = function(num){ if(num===1){ return ; } return num * arguments.callee(num-1); }
這種方式可以避免當函式名改變時導致的遞迴報錯
然而為了安全性,在嚴格環境下無法使用
所以嚴格環境可以使用下面的程式碼來實現該功能
var test = function lhy(num){ if(num===1){ return ; } return num * lhy(num-1); }
除此而外函式例項上還有一個屬性 caller
用於儲存呼叫當前函式的函式的引用,全域性環境下該值為 null
函式屬性和方法
每個函式都包含以下兩個屬性:
1.length 表示函式希望獲得引數的個數
2.prototype 跟原型鏈相關,在此不過多介紹
除了上述方法之外,函式還包括3個非繼承而來的方法
1.applay()
2.call()
3.bind()
這三個方法的作用十分類似,都是用於改變函式的 this 指向
其中 applay 和 call 都是改變指向並執行,而 bind 只改變函式指向並不會立即執行(只接收一個引數即要繫結的物件)
而apply和call的第一個引數都是this指向的物件,區別在於:
call方法的的引數必須一一例舉
而apply只需要接收兩個引數,第二引數是引數陣列
所以使用時要視具體情況而定
JS中的函式與原型無關的地方就介紹完了,原型相關的內容在後面的文章介紹
明天再見~~