天天看點

【javascript基礎】2、函數前言函數小結

PS:最近jQuery源碼交流群( 239147101)加了不少熱新人,希望大家還是以學習為主,盡量少灌水,給大家一個好的提升自己的環境。

函數在任何一種程式設計語言中都是一個很重要的結構或者組成部分,程式設計中的複雜結構和功能都會有函數的參與。javascript中的函數是一個對象,函數對象時Function類型的執行個體,由于Function類型是一個引用類型,那麼函數可以擁有自己的方法和屬性,同時也因為函數是一個對象,那麼函數名是一個指向函數對象的指針,可以被指派。下面詳細介紹函數的各個部分。

函數的建立有三種方式,分别為使用Function的構造函數、函數聲明、函數表達式,下面分别介紹這三種方法。

這種方式是直接new出來一個Function 執行個體,通過使用Function的構造函數進行建立函數。Function構造函數可以接收任意多個參數,但是最後一個參數會被認為是函數體,前面的是以參數被當做被建立出來的函數的參數。

我們可以看出比較的麻煩,并且《javascript進階程式設計》也不推薦我們使用這種方式,主要是因為浏覽器要解析正常的javascript代碼之外,還要解析傳入的參數字元串,這個類似eval()的解釋,影響性能。

這種方式是建立的常見方式之一,具體請看

上面的代碼就是建立一個函數,使用test()進行調用。其實,上面的代碼是先建立了一個匿名的函數,之後把這個匿名的函數指派給test變量。每個函數有一個name屬性,這個屬性不是ECMA标準的一部分,但是許多地方可以使用它。我們可以給上面的函數起一個名字,具體下面代碼

這個屬性在後面詳細解釋吧。

這種方式和C語言中的很類似,這種是最常見的一種建立函數的方法。是通過關鍵字function直接聲明,請看

以上介紹了三個建立函數的方式,現在介紹三種的差別,确切的說是後兩種的差別,因為Function不推薦使用,性能是一大原因。差別就是使用函數聲明這種方式會使函數的聲明提前,類似前面我們提到的變量申明的提前。也就是說,使用函數申明方式,我們可以将函數的聲明放在調用函數代碼的後面,因為解析器會在代碼執行之前将函數的聲明提升,提到源代碼樹的頂部,而函數表達式方式則會報錯,具體請看

javascript語言不像java那些語言有函數重載這一概念,其實函數名就是一個指針,指向一個Function執行個體的位址,當然隻能指向一個函數,當然沒有重載的概念了,隻有覆寫,後面定義的函數覆寫前面定義的函數,具體請看

也就是說如果一個同名的函數表達式和函數申明的函數在一起,無論位置是怎麼樣的,最後的函數就會是用函數表達式建立的函數,因為函數申明會提升到頂部嘛,看看下面的代碼

函數的内部有兩個重要的對象:arguments和this。

arguments是一個類似組對象,包含是以傳入函數的所有參數, 寫程式或者面試中常問的就是如何将arguments轉化完成一個數組,請看

arguments有一個length屬性,表示函數傳入參數的個數,還有一個callee屬性,這是一個指針,指向擁有這個arguments的函數,這個主要是在函數内部調用自己時使用,也就是遞歸時使用。看個例子就明白了

 javascript中的this和java中的this差不多,this引用的是函數的執行環境,就是this在不同的執行環境中引用的是不同的對象,執行環境這裡還沒有說到,以後會詳細介紹,這裡的this也是簡單的介紹一下,我以後會整理一些面試題,幫助大家了解。看例子吧,

解釋一下,this這個對象是在函數執行時才綁定的,可以說是一個動态的。pop函數是定義在window下的一個函數,也就是全局作用域的一個函數,當直接執行pop函數時,就是在全局作用域下調用pop時。this引用的是window,this.color就是window.color,輸出red。當我們把pop這個函數指派給obj這個對象并且調用pop的時候,this引用的就是obj這個對象,this.color 就是obj.color,輸出blue。

這裡說一下函數的屬性和方法,包括length,name,prototype,apply,call這幾個。

這個屬性比較簡單,就是表示定義函數時定義的參數的個數,要和arguments.length區分開,arguments.length表示實際輸入的參數個數,看例子

這個屬性在前面提到了一點,這個就是函數的名字,我們在建立函數的時候說了這個屬性,這個屬性不是标準屬性,但是很多地方就使用這個屬性,主要也是在遞歸調用上使用。name屬性是隻讀屬性,不能修改它的值。直接看例子

name屬性的使用和arguments.callee()的效果是一樣的,隻不過arguments.callee()更友善些,當函數名字更改時程式不用更改。

函數的prototype屬性是一個很重要的屬性,特别是在自定義引用類型和實作繼承時。我們現在這簡單的介紹一下它,因為這個屬性足以單獨寫一篇文章。我們可以認為prototype是一個模闆,在new 一個對象時候會參照這個模闆,将模闆裡的屬性和方法複制給對象,當然你不定義這個模闆,這個模闆不存在方法和屬性。簡單例子

先簡單介紹到這,後面單獨詳細說。

這兩個方法作用是一樣的,就是改變this作用域的值,在特定的作用域中調用自己,也就是設定this的指向,不同點在于參數接收方式不同。apply方法需要兩個參數,第一個是指定的作用域,就是要把this指向的對象,第二個是參數數組,函數調用需要的參數,這個參數數組也可以是arguments這個僞數組。call的第一個參數也是給this綁定的值,其他的參數個數不定,其他的參數就是函數調用需要的參數,和apply不同,你要一個一個的都列舉出來。看例子

上面是傳遞參數的例子,再看看改變this指向的例子

解釋一下,pop.call(this)這句代碼改變了this的指向,因為是在全局中調用的函數,this指向window,輸出window.color。pop.call(obj)這句代碼将this指向了obj,是以輸出obj.color。

把函數這部分的基礎和大家說了一下,自己講代碼敲了一遍實驗了一下,有些東西看着容易懂,寫起來還是挺困難的,希望大家也要多寫寫吧,我一直以為作文就不好,這是難為大家了。要放假了,有點想家了,想吃家裡的酸菜了。